Source: advancedProgramming [edit]

Advanced Programming in WubHub

This page describes how to program new functions in WubHub. Read the introductory help page first, and the introduction to programming.

Working with Lucene

Simple functions have been created to let you work with Lucene, both for search and local search. Generally, the pattern is:

  • You get a lucene index for reading -- Wub_ReadLuceneIndex(indexName) -- or writing -- Wub_NewLuceneIndex(indexName, create)
  • You create a document, add fields to it, and then add the document to the index -- Wub_NewLuceneDocument(), Wub_AddLuceneField(doc, name, content, store, analyze), Wub_AddLuceneLatLongField(doc, lat, lng), Wub_AddLuceneDocument(writer, doc)
  • You read the index for search or local search -- Wub_LuceneSearch(reader, defaultField, query, hitsPerPage), Wub_LocalSearch(reader, lat, lon, miles defaultField, query, hitsPerPage, calculateDistances, sortByDistances)
  • You optimize (if writing) and then close the index -- Wub_OptimizeLucene(writer), Wub_CloseLuceneIndex(writerOrReader)
  • A few miscellaneous other functions exist -- Wub_DeleteLuceneDocuments(writer, term, doc), Wub_UpdateLuceneDocument(writer, term, doc), Wub_NewLuceneTerm(fieldName, searchStr)
Here is an example of usage:

Writing example

/* Adds a person object to the search index  */
addPerson = fun(person)
   var ok = true;

   // create is false, add to existing index.  "standard" analysis (no stemming). For stemming: "kstem" and "english" (porter)
   var writer = Wub_NewLuceneIndex("resumes", false, "standard"); 
   var doc = Wub_NewLuceneDocument();

  // Add fields to doc
   ok = ok and Wub_AddLuceneField(doc, "id", person["id"], true, true, 0); // 0 = no special boost
   ok = ok and Wub_AddLuceneField(doc, "name", person["name"], true, true, 0);
   ok = ok and Wub_AddLuceneField(doc, "headline", (person["headline"] ? ""), true, true, 0);
   ok = ok and Wub_AddLuceneField(doc, "industry", (person["industry"]?""), true, true, 0);
   ok = ok and Wub_AddLuceneField(doc, "salary", (ToString(person["salary"])?""), true, true, 0);

   // Add coordinates for local search
   ok = ok and Wub_AddLuceneLatLongField(doc, ToReal(person["lat"]), ToReal(person["lng"]));

   ok = ok and Wub_AddLuceneDocument(writer, doc);
   ok = ok and Wub_OptimizeLucene(writer);
   ok = ok and Wub_CloseLuceneIndex(writer);
end;

Searching Example

   var reader = Wub_ReadLuceneIndex("resumes");
   var docs = Wub_LuceneSearch(reader, "skills", queryString, 20, "standard"); // use same analyzer as was indexed with
   Wub_CloseLuceneIndex(reader);

   var i = 0;
   var sz = (docs.size() ? 0);

   while (i < sz) do
      var doc = docs.get(i).getDoc();
      var explaination = docs.get(i).getExplanation(); // explains score

      var d = [. .];
      d["id"] := doc.getField("id").stringValue();
      d["name"] := doc.getField("name").stringValue();
      d["headline"] := doc.getField("headline").stringValue();
      d["industry"] := doc.getField("industry").stringValue();
      d["salary"] := doc.getField("salary").stringValue();
      d["explanation"] := explanation;

      res = res + [d];
      i = i + 1
   end;
   res;

Working with Tries

Simple functions have been created to let you work with Trie data structure:

  • addToTrie(trie, term, dataType, data): Returns a trie that adds a new term to an existing trie, with dataType=[data] set at the terminal value. If the same term is added more than once, each of the data elements are added to the dateType list.
  • lookupInTrie(trie, term, dataType): Returns the list of data values associated with dataType for a term, or nil if term is not found.
The empty trie is [. .]. Here is an example of usage:
var trie = [. .];   // initial trie to empty

trie = WubCall("addToTrie", [ trie, "ab", "data", "1"] );
trie = WubCall("addToTrie", [ trie, "ab", "data", "2"] );
trie = WubCall("addToTrie", [ trie, "a", "data", "3"] );
trie = WubCall("addToTrie", [ trie, "def", "data", "4"] );

// Returns some values;
WubCall("lookupInTrie", [ trie, "ab", "data"] );    // returns [1, 2]
WubCall("lookupInTrie", [ trie, "def", "data"] );   // returns [4]
WubCall("lookupInTrie", [ trie, "xyz", "data"] );   // returns nil

Working with MongoDB

To work with the MongoDB database, follow the following steps:
  • Get a reference to a named database. This command either creates a new one or accesses an existing one.

    var db = Wub_GetDB("humanResources");

  • Get a reference to a collection (like a table).

    var coll = Wub_GetCollection(db, "employees");

  • Create a DB Object (row) to insert into the collection.

    var dbobj = Wub_NewDBObject([. name="Adam Cheyer", salary=100000.00, age=45 .]);
    Wub_InsertDB(coll, dbobj);

  • To query the database, create a query object and call the QueryDB function:

    var dbobj = Wub_NewDBObject([. name="Adam Cheyer" .]);
    var res = Wub_QueryDB(coll, dbobj, 20); // 20 = max results

  • Query objects can search fields using comparative operators ($all, $gt, $gte, $in, $lt, $lte, $ne, $nin):

    var dbobj = Wub_NewDBObject([. "age"=[. "$gt"=40 .] .]);
    var res = Wub_QueryDB(coll, dbobj, 20);

  • You can update records using a search object and an update object with update operators ($set, $unset, $inc, $rename). If the Upsert parameter is true, it will insert an object if a replace doesn't occur. If Multi is true, it will make the update on all changes, otherwise just on the first:

    var upobj = Wub_NewDBObject([. "$set" = [. "age"=46 .] .]);
    var res = Wub_UpdateDB(coll, dbobj, upobj, false, false);

  • You can drop an entire database:

    var upobj = Wub_DropDB("employees");

  • Or remove individual records matching a query:

    Wub_RemoveDB(collection, queryObj);

  • You can get the number of records in a collection:

    coll.count();

More Information