Elycite - Routing - Main Module
(c) 2013-2014 Luis Rei, Josef Stefan Institute MIT License
var analytics = require('analytics.js');
var restf = require('restf.js');
var stores = require('stores.js');
var documents = require('documents.js');
var concepts = require('concepts.js');
var al = require('activelearning.js');
var cls = require('classifiers.js');
params
to be replaced accordingly.args
that take the value hello and world, respectively.Method: GET
Description: Get Language Options
Returns: Options for stemmers and stopword lists
{ stemmer: [“none”, “porter”], stopwords: [“none”, “en8”, …] }
http.onRequest("languageoptions", "GET", function(req, res) {
console.say("elycite API - Language Options");
var LangOpts = analytics.getLanguageOptions();
res.send(LangOpts);
});
METHOD: GET
Description: Get List of available Data (Document) Stores
Returns: A list of qminer store definitions
http.onRequest("stores", "GET", function(req, res) {
console.say("elycite API - GET Stores");
stores.listStores(res);
});
METHOD: POST
Description: Create a data (document) store with records
JSON DATA:
{
storeName: "exampleName",
records: [{RecVal1}, ...]
}
http.onRequest("stores/", "POST", function(req, res) {
console.say("elycite API - POST Stores");
var data = restf.requireJSON(req, res, "storeName", "records");
if(data === null) { return; }
stores.createStore(res, data);
});
Get a single store definition by name @TODO: NOT IMPLEMENTED
http.onRequest("stores/<store>", "GET", function(req, res) {
console.say("elycite API - GET Stores");
res.setStatusCode(501);
res.send();
});
Example ontology
document (JSON representation):
{
$id: 3,
name: "textmining",
docStore: "news",
classifierStore: "textmining_cls",
isDeleted: false,
links: {
self: "/elyciteapi/ontologies/textmining/",
concepts: "/elyciteapi/ontologies/textmining/concepts/"
}
}
METHOD: GET
Description: Get List of Existing Ontologies
Returns: list of ontology
documents
[OntologyDocument1, OntologyDocument2, …]
http.onRequest("ontologies", "GET", function(req, res) {
console.say("elycite API - GET Existing Ontologies");
stores.listOntologies(res);
});
METHOD: POST
Description: Create a new ontology
JSONDATA:
{
ontologyName: "new_ontology",
dataStore:"news_data"
}
Returns: the ontology
Example Request:
curl -H "Content-Type: application/json" -d \
'{"ontologyName":"textmining","dataStore":"news"}' \
http://localhost:8080/elyciteapi/ontologies
http.onRequest("ontologies", "POST", function(req, res) {
console.say("elycite API - Create Ontology: ");
var data = restf.requireJSON(req, res, "ontologyName", "dataStore");
if(data === null) { return; }
stores.createOntology(res, data);
});
METHOD: GET
Description: Read ontology definition
PARAMS:
Returns: the ontology
JSON representation. See above.
http.onRequest("ontologies/<ontology>/", "GET", function (req, res) {
console.say("elycite API - Concept ontology def");
var params = restf.requireParams(req, res, "ontology");
if(params === null) { return; }
var store = stores.requireExists(res, params.ontology);
if(store === null) { return; }
stores.getOntology(res, store);
});
A document is a record from the data store associated with the ontology. It includes all fields in the data (qminer( record. Text fields can optionally be summarized (truncated).
METHOD: GET
Description: Get All Documents - Summaries only by default
PARAMS:
ARGS:
per_page
documentsRETURNS: list of document
s (see above).
Example:
curl -X GET \
"http://localhost:8080/elyciteapi/ontologies/test/documents/?page=3&per_page=2&summarize=true?"
http.onRequest("ontologies/<ontology>/documents/", "GET", function (req, res) {
console.say("elycite API - Document GET ALL (summaries)");
var params = restf.requireParams(req, res, "ontology");
if(params === null) { return; }
var store = stores.requireExists(res, params.ontology);
if(store === null) { return; }
documents.getDocuments(req, res, store);
});
METHOD: GET
Description: Read Document
PARAMS:
RETURNS: a single document
http.onRequest("ontologies/<ontology>/documents/<did>/", "GET",
function (req, res) {
console.say("elycite API - Document <did> GET");
var params = restf.requireParams(req, res, "ontology", "did");
if(params === null) { return; }
var store = stores.requireExists(res, params.ontology);
if(store === null) { return; }
var docId = restf.requireInt(res, "did", params.did);
if(docId === null) { return; }
documents.getDocument(res, store, params.ontology, docId);
});
{
$id: 0,
name: "root",
keywords: "",
stopwords: "none",
stemmer: "none",
isDeleted: false,
classifiers: [ ],
parentId: -1,
ontology: "textmining",
links: {
self: "/elyciteapi/ontologies/textmining/concepts/0/",
ontology: "/elyciteapi/ontologies/textmining/"
}
}
METHOD: GET
Description: Get all concept
s (see above)
PARAMS:
ARGS:
RETURNS: a list of concept
s
http.onRequest("ontologies/<ontology>/concepts/", "GET", function (req, res) {
console.say("elycite API - Concept GET ALL");
var params = restf.requireParams(req, res, "ontology");
if(params === null) { return; }
var store = stores.requireExists(res, params.ontology);
if(store === null) { return; }
concepts.getConcepts(res, store, params.ontology);
});
METHOD: POST
Description: Create a concept
PARAMS:
JSONDATA: A JSON representation of non-calculated concept
properties.
concept
‘s nameconcept
concept
EXAMPLE REQUEST:
curl -H "Content-Type: application/json" -d \
'{"name":"testc", "parentId":0, "docs":[0,1,3]}' \
http://localhost:8080/elyciteapi/ontologies/textmining/concepts/
http.onRequest("ontologies/<ontology>/concepts/", "POST",
function (req, res) {
console.say("elycite API - Concept POST");
var params = restf.requireParams(req, res, "ontology");
if(params === null) { return; }
var store = stores.requireExists(res, params.ontology);
if(store === null) { return; }
var data = restf.requireJSON(req, res, "name", "parentId");
if(data === null) { return; }
concepts.createConcept(res, data, store, params.ontology);
});
METHOD: GET
Description: Get a single concept
PARAMS:
concept
to getRETURNS: the concept
http.onRequest("ontologies/<ontology>/concepts/<cid>/", "GET",
function (req, res) {
console.say("elycite API - Concept GET");
var params = restf.requireParams(req, res, "ontology", "cid");
if(params === null) { return; }
var store = stores.requireExists(res, params.ontology);
if(store === null) { return; }
var conceptId = restf.requireInt(res, "cid", params.cid);
if(conceptId === null) { return; }
var concept = stores.requireRecord(res, store, "concept", conceptId);
if(concept === null) { return; }
concepts.getConcept(res, store, concept);
});
METHOD: PUT
Description: Edit a concept
PARAMS:
cid - the record id of the concept do edit
JSONDATA:
name (string, optional) - the concept
‘s name
concept
EXAMPLE REQUEST:
curl -X PUT -H "Content-Type: application/json" -d '{"name":"hello"}' \
http://localhost:8080/elyciteapi/ontologies/textmining/concepts/1/
http.onRequest("ontologies/<ontology>/concepts/<cid>/", "PUT",
function (req, res) {
console.say("elycite API - Concept edit PUT");
var params = restf.requireParams(req, res, "ontology", "cid");
if(params === null) { return; }
var store = stores.requireExists(res, params.ontology);
if(store === null) { return; }
var data = restf.requireJSON(req, res);
if(data === null) { return; }
var conceptId = restf.requireInt(res, "cid", params.cid);
if(conceptId === null) { return; }
var concept = stores.requireRecord(res, store, "concept", conceptId);
if(concept === null) { return; }
concepts.editConcept(res, concept, data, store, params.ontology);
});
METHOD: DELETE
Description: Delete this concept
including subconcepts (recursively).
PARAMS:
EXAMPLE REQUEST:
curl -X DELETE \
http://localhost:8080/elyciteapi/ontologies/textmining/concepts/1/
http.onRequest("ontologies/<ontology>/concepts/<cid>/", "DELETE",
function (req, res) {
console.say("elycite API - Concept DELETE");
var params = restf.requireParams(req, res, "ontology", "cid");
if(params === null) { return; }
var store = stores.requireExists(res, params.ontology);
if(store === null) { return; }
var conceptId = restf.requireInt(res, "conceptId", params.cid);
if(conceptId === null) { return; }
var concept = stores.requireRecord(res, store, "concept", conceptId);
if(concept === null) { return; }
concepts.deleteConcept(res, concept, store);
});
METHOD: GET
Description: get a list of concept
s that are subsconcepts (children)
of this concept
PARAMS:
RETURNS: an array containing concept
s that are the concept
‘s
subconcepts (children)
http.onRequest("ontologies/<ontology>/concepts/<cid>/subconcepts/", "GET",
function (req, res) {
console.say("elycite API - GET SUB CONCETPS");
var params = restf.requireParams(req, res, "ontology", "cid");
if(params === null) { return; }
var store = stores.requireExists(res, params.ontology);
if(store === null) { return; }
var conceptId = restf.requireInt(res, "cid", params.cid);
if(conceptId === null) { return; }
var concept = stores.requireRecord(res, store, "concept", conceptId);
if(concept === null) { return; }
concepts.getSubConcepts(res, concept, store, params.ontology);
});
METHOD: GET
Description: Get a list of document
record ids that are in the
concept
PARAMS:
RETURNS: an array of document
record ids (ints)
http.onRequest("ontologies/<ontology>/concepts/<cid>/docs/", "GET",
function (req, res) {
console.say("elycite API - Concept GET docs");
var params = restf.requireParams(req, res, "ontology", "cid");
if(params === null) { return; }
var store = stores.requireExists(res, params.ontology);
if(store === null) { return; }
var conceptId = restf.requireInt(res, "conceptId", params.cid);
if(conceptId === null) { return; }
var concept = stores.requireRecord(res, store, "concept", conceptId);
if(concept === null) { return; }
concepts.getConceptDocuments(req, res, concept, store);
});
METHOD: PATCH
DESCRIPTION: Edit the list of document
record ids in the concept
(Select, DeSelect)
PARAMS:
JSONDATA:
document
to add or remove from the concept
operation (string) - “add” or “del” to add or remove, respectively, the
document
id from the listRETURNS: an array with the document
record ids in the concept
EXAMPLE REQUEST:
curl -X PATCH -H "Content-Type: application/json" \
-d '{"docId":20, "operation":"add"}' \
http://localhost:8080/elyciteapi/ontologies/demo/concepts/1/docs/
http.onRequest("ontologies/<ontology>/concepts/<cid>/docs/", "PATCH",
function (req, res) {
console.say("elycite API - Concept Edit doc list");
var params = restf.requireParams(req, res, "ontology", "cid");
if(params === null) { return; }
var store = stores.requireExists(res, params.ontology);
if(store === null) { return; }
var conceptId = restf.requireInt(res, "conceptId", params.cid);
if(conceptId === null) { return; }
var concept = stores.requireRecord(res, store, "concept", conceptId);
if(concept === null) { return; }
concept = restf.requireNotDeleted(concept, "concept");
if(concept === null) { return; }
var data = restf.requireJSON(req, res, "operation", "docId");
if(data === null) { return; }
var docId = restf.requireInt(res, "docId", data.docId);
if(docId === null) { return; }
concepts.editConceptDocuments(res, docId, data.operation, concept, store);
});
METHOD: GET
Description: Get keyword suggestions for a concept
PARAMS:
ARGS:
RETURNS: a JSON object with a keywords
string property consisting of
the suggested keywords separated by a comma an a space. Example:
{
"keywords":"services, bank, business, management, markets"
}
http.onRequest("ontologies/<ontology>/concepts/<cid>/suggestkeywords/", "GET",
function (req, res) {
console.say("elycite API - Concept/suggeskeywords");
var params = restf.requireParams(req, res, "ontology", "cid");
if(params === null) { return; }
var store = stores.requireExists(res, params.ontology);
if(store === null) { return; }
var conceptId = restf.requireInt(res, "conceptId", params.cid);
if(conceptId === null) { return; }
var concept = stores.requireRecord(res, store, "concept", conceptId);
if(concept === null) { return; }
concept = restf.requireNotDeleted(concept, "concept");
if(concept === null) { return; }
var args = req.args || {};
concepts.getKeywordSuggestions(res, args, concept);
});
METHOD: GET
Description: Suggest a subconcept based on search
PARAMS:
ARGS:
RETURNS: a concept suggestion (concept
without id or generated
properties). Example:
{
name: "software",
keywords: "services, solutions, systems, management, technology, network",
parentId: 0,
docs: [3, 5, ...]
}
http.onRequest("ontologies/<ontology>/concepts/<cid>/search/", "GET",
function (req, res) {
console.say("elycite API - Concept/Search");
var params = restf.requireParams(req, res, "ontology", "cid");
if(params === null) { return; }
var store = stores.requireExists(res, params.ontology);
if(store === null) { return; }
var conceptId = restf.requireInt(res, "conceptId", params.cid);
if(conceptId === null) { return; }
var concept = stores.requireRecord(res, store, "concept", conceptId);
if(concept === null) { return; }
concept = restf.requireNotDeleted(concept, "concept");
if(concept === null) { return; }
var args = restf.requireArgs(req, res, "query");
if(args === null) { return; }
concepts.getConceptSuggestionFromQuery(res, concept, store, args.query);
});
METHOD: GET
Description: Suggest subconcepts (clustering based)
PARAMS:
ARGS:
concept
suggestionsRETURNS: an array of concept suggestions (concept
s without id or
generated properties). See the return of /search/ above.
http.onRequest("ontologies/<ontology>/concepts/<cid>/suggest/", "GET",
function (req, res) {
console.say("elycite API - Concept GET suggestions");
var params = restf.requireParams(req, res, "ontology", "cid");
if(params === null) { return; }
var store = stores.requireExists(res, params.ontology);
if(store === null) { return; }
var conceptId = restf.requireInt(res, "conceptId", params.cid);
if(conceptId === null) { return; }
var concept = stores.requireRecord(res, store, "concept", conceptId);
if(concept === null) { return; }
concept = restf.requireNotDeleted(concept, "concept");
if(concept === null) { return; }
concepts.getConceptSuggestionsByClustering(req, res, concept, store);
});
While there is no actual “active learner document”, there is a question
document where the id
attribute refers to the AL and the questionId is the
id of the data associated with the question:
{
“questionId”:128,
“id”:”medical_1936769238”,
“links”:{
“self”:”/elyciteapi/ontologies/undefined/concepts/0/al/medical_1936769238/“
},
“text”:”Develops and manages medical facilities…”,
“mode”:false
}
If mode is true, the question
also includes all necessary information to
create a new concept
{
…
“mode”:true,
“count”:518,
“docs”:[75,…],
“name”: “medical, services, products”,
“keywords”:, “medical, …”
}
METHOD: POST
Description: Create Active Learner for a given query
PARAMS:
JSONDATA:
RETURNS: An initial question
.
http.onRequest("ontologies/<ontology>/concepts/<cid>/al/", "POST",
function (req, res) {
console.say("elycite API - AL Create - POST");
var params = restf.requireParams(req, res, "ontology", "cid");
if(params === null) { return; }
var store = stores.requireExists(res, params.ontology);
if(store === null) { return; }
var conceptId = restf.requireInt(res, "conceptId", params.cid);
if(conceptId === null) { return; }
var concept = stores.requireRecord(res, store, "concept", conceptId);
if(concept === null) { return; }
concept = restf.requireNotDeleted(concept, "concept");
if(concept === null) { return; }
var data = restf.requireJSON(req, res, "query");
var query = data.query;
al.create(res, data, concept, store, query);
});
METHOD: GET
Description: Get a question from an active learner.
PARAMS:
RETURNS: A question
.
http.onRequest("ontologies/<ontology>/concepts/<cid>/al/<alid>/", "GET",
function (req, res) {
console.say("elycite API - AL/name/ GET");
var params = restf.requireParams(req, res, "ontology", "cid", "alid");
if(params === null) { return; }
var store = stores.requireExists(res, params.ontology);
if(store === null) { return; }
var conceptId = restf.requireInt(res, "conceptId", params.cid);
if(conceptId === null) { return; }
var concept = stores.requireRecord(res, store, "concept", conceptId);
if(concept === null) { return; }
concept = restf.requireNotDeleted(concept, "concept");
if(concept === null) { return; }
var name = params.alid;
al.getQuestion(res, name, concept, params.ontology);
});
METHOD: PATCH
Description: Answer a question from an active learner.
PARAMS:
JSONDATA:
RETURNS: The next question
.
http.onRequest("ontologies/<ontology>/concepts/<cid>/al/<alid>/", "PATCH",
function (req, res) {
console.say("elycite API - AL/name/ PATCH");
var params = restf.requireParams(req, res, "ontology", "cid", "alid");
if(params === null) { return; }
var store = stores.requireExists(res, params.ontology);
if(store === null) { return; }
var conceptId = restf.requireInt(res, "conceptId", params.cid);
if(conceptId === null) { return; }
var concept = stores.requireRecord(res, store, "concept", conceptId);
if(concept === null) { return; }
concept = restf.requireNotDeleted(concept, "concept");
if(concept === null) { return; }
var data = restf.requireJSON(req, res, "answer", "did");
var did = restf.requireInt(res, "did", data.did); // actually did
var name = params.alid;
al.answerQuestion(res, name, concept, params.ontology, did, data.answer);
});
METHOD: DELETE
Description: Cancel (DELETE) active learner.
PARAMS:
http.onRequest("ontologies/<ontology>/concepts/<cid>/al/<alid>/", "DELETE",
function (req, res) {
console.say("elycite API - AL/name/ DELETE");
var params = restf.requireParams(req, res, "ontology", "cid", "alid");
if(params === null) { return; }
var store = stores.requireExists(res, params.ontology);
if(store === null) { return; }
var conceptId = restf.requireInt(res, "conceptId", params.cid);
if(conceptId === null) { return; }
var concept = stores.requireRecord(res, store, "concept", conceptId);
if(concept === null) { return; }
concept = restf.requireNotDeleted(concept, "concept");
if(concept === null) { return; }
var name = params.alid;
al.cancel(res, name);
});
METHOD: POST
Description: Get Concept: finish active learning and create the concept
PARAMS:
RETURNS: The concept
created.
http.onRequest("ontologies/<ontology>/concepts/<cid>/al/<alid>/",
"POST", function (req, res) {
console.say("elycite API - AL/name/ POST");
var params = restf.requireParams(req, res, "ontology", "cid", "alid");
if(params === null) { return; }
var store = stores.requireExists(res, params.ontology);
if(store === null) { return; }
var conceptId = restf.requireInt(res, "conceptId", params.cid);
if(conceptId === null) { return; }
var concept = stores.requireRecord(res, store, "concept", conceptId);
if(concept === null) { return; }
concept = restf.requireNotDeleted(concept, "concept");
if(concept === null) { return; }
var name = params.alid;
al.finish(res, name, concept);
});
{
“id”:”classifier_name”,
“links”:{
“self”:”/elyciteapi/ontologies/blahblah/classifiers/classifier_name/“,
“ontology”:”/elyciteapi/ontologies/blahblah/“
}
}
METHOD: POST
Description: List existing classifiers (models).
PARAMS:
RETURNS: A list of classifier
s.
http.onRequest("ontologies/<ontology>/classifiers/", "GET",
function (req, res) {
console.say("elycite API - Classifiers Get");
var params = restf.requireParams(req, res, "ontology");
if(params === null) { return; }
var store = stores.requireExists(res, params.ontology);
if(store === null) { return; }
cls.list(res, store);
});
METHOD: POST
Description: Create classifier for a Concept.
PARAMS:
JSONDATA:
RETURNS: The classifier
created.
http.onRequest("ontologies/<ontology>/classifiers/", "POST",
function (req, res) {
console.say("elycite API - Concept Classifier - POST");
var params = restf.requireParams(req, res, "ontology");
if(params === null) { return; }
var store = stores.requireExists(res, params.ontology);
if(store === null) { return; }
var data = restf.requireJSON(req, res, "name", "cid");
var conceptId = restf.requireInt(res, "conceptId", data.cid);
if(conceptId === null) { return; }
var concept = stores.requireRecord(res, store, "concept", conceptId);
if(concept === null) { return; }
concept = restf.requireNotDeleted(concept, "concept");
if(concept === null) { return; }
cls.create(res, data, concept, store, params.ontology);
});
METHOD: POST
Description: Classify array of documents.
PARAMS:
RETURNS: An array of decision functions (negative or positive numbers).
Example:
curl -X POST -H “Content-Type: application/json” \
-d ‘[“this is about networks”, “this is dog”]’ \
http://localhost:8080/elyciteapi/ontologies/worktest/classifiers/worktest_network/
http.onRequest("ontologies/<ontology>/classifiers/<mid>/", "POST",
function (req, res) {
console.say("elycite API - Classify with model POST");
var params = restf.requireParams(req, res, "ontology", "mid");
if(params === null) { return; }
var store = stores.requireExists(res, params.ontology);
if(store === null) { return; }
var data = restf.requireJSON(req, res);
cls.classify(res, params.mid, data, store);
});
METHOD: DELETE
Description: Delete a classifier (with ontology parameter).
PARAMS:
http.onRequest("ontologies/<ontology>/classifiers/<mid>/", "DELETE",
function (req, res) {
console.say("elycite API - DELETE Classifier");
var params = restf.requireParams(req, res, "mid");
if(params === null) { return; }
var mid = params.mid;
cls.deleteClassifier(mid);
res.send();
});
METHOD: POST
Description: Get (binary) subsconcepts from classifier.
PARAMS:
RETURNS: Array with positive and negative subconcept
s.
http.onRequest("ontologies/<ontology>/concepts/<cid>/classify/<mid>/", "GET",
function (req, res) {
console.say("elycite API - GET SUB CONCETPS FROM CLASSIFIER");
var params = restf.requireParams(req, res, "ontology", "cid", "mid");
if(params === null) { return; }
var store = stores.requireExists(res, params.ontology);
if(store === null) { return; }
var conceptId = restf.requireInt(res, "conceptId", params.cid);
if(conceptId === null) { return; }
var concept = stores.requireRecord(res, store, "concept", conceptId);
if(concept === null) { return; }
concept = restf.requireNotDeleted(concept, "concept");
if(concept === null) { return; }
var args = req.args || {};
var threshold = restf.optionalFloat(args, "thresh", 0);
var mid = params.mid;
cls.subConcepts(res, mid, threshold, concept, store);
});
METHOD: GET
Description: List existing classifiers (models) for ALL ontologies
RETURNS: A list of classifier
s.
http.onRequest("classifiers/", "GET", function (req, res) {
console.say("elycite API - Classifiers Get ALL");
cls.listAll(res);
});
METHOD: DELETE
Description: Delete a classifier (without ontology parameter)
PARAMS:
http.onRequest("classifiers/<mid>/", "DELETE", function (req, res) {
console.say("elycite API - DELETE Classifier");
var params = restf.requireParams(req, res, "mid");
if(params === null) { return; }
var mid = params.mid;
cls.deleteClassifier(mid);
res.send();
});