Can now search index and obtain results object (always capitalized summaries)
authorNick Downing <downing.nick@gmail.com>
Thu, 4 Jan 2018 10:07:36 +0000 (21:07 +1100)
committerNick Downing <nick@ndcode.org>
Sun, 18 Nov 2018 02:37:55 +0000 (13:37 +1100)
test.js
zetjs.cpp

diff --git a/test.js b/test.js
index d226268..110af5b 100755 (executable)
--- a/test.js
+++ b/test.js
@@ -3,9 +3,4 @@
 const zet = require('./build/Release/zet');
 
 const obj = new zet.Index();
-console.log(obj.plusOne());
-// Prints: 11
-console.log(obj.plusOne());
-// Prints: 12
-console.log(obj.plusOne());
-// Prints: 13
+console.log(obj.search('moby', 0, 10));
index 6bcf653..6688485 100644 (file)
--- a/zetjs.cpp
+++ b/zetjs.cpp
@@ -1,5 +1,8 @@
 #include <node.h>
 #include <node_object_wrap.h>
+//#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
 
 #include "def.h"
 #include "fdset.h"
 
 namespace zetjs {
 
+static v8::Local<v8::Object> index_result_to_object(
+  v8::Isolate* isolate,
+  struct index_result* result
+);
+static v8::Local<v8::Object> index_results_to_object(
+  v8::Isolate* isolate,
+  struct index_result* results,
+  unsigned int num_results,
+  double/*unsigned long int*/ total_results
+);
+
 class IndexObject : public node::ObjectWrap {
 public:
   static void Init(v8::Local<v8::Object> exports);
 
 private:
   struct index* idx;
-  double value_;
 
-  explicit IndexObject(struct index* idx);
+  explicit IndexObject(struct index* idx0);
   ~IndexObject();
 
   static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
-  static void PlusOne(const v8::FunctionCallbackInfo<v8::Value>& args);
+  static void Search(const v8::FunctionCallbackInfo<v8::Value>& args);
   static v8::Persistent<v8::Function> constructor;
 };
 
 v8::Persistent<v8::Function> IndexObject::constructor;
 
-IndexObject::IndexObject(struct index* idx0) : idx(idx0), value_(0.) {
+IndexObject::IndexObject(struct index* idx0) : idx(idx0) {
 }
 
 IndexObject::~IndexObject() {
@@ -48,7 +61,7 @@ void IndexObject::Init(v8::Local<v8::Object> exports) {
   tpl->InstanceTemplate()->SetInternalFieldCount(1);
 
   // Prototype
-  NODE_SET_PROTOTYPE_METHOD(tpl, "plusOne", PlusOne);
+  NODE_SET_PROTOTYPE_METHOD(tpl, "search", Search);
 
   constructor.Reset(isolate, tpl->GetFunction());
   exports->Set(
@@ -62,8 +75,7 @@ void IndexObject::New(const v8::FunctionCallbackInfo<v8::Value>& args) {
 
   if (args.IsConstructCall()) {
     // Invoked as constructor: `new Index(...)`
-    v8::String::Utf8Value* prefix =
-      args[0]->IsUndefined() ? NULL : new v8::String::Utf8Value(args[0]);
+    v8::String::Utf8Value prefix(args[0]);
     struct index* idx = NULL;;
     int lopts = INDEX_LOAD_NOOPT;
     struct index_load_opt lopt;
@@ -72,7 +84,7 @@ void IndexObject::New(const v8::FunctionCallbackInfo<v8::Value>& args) {
     if (
       (
         idx = index_load(
-          prefix ? **prefix : "index",
+          args[0]->IsString() ? *prefix : "index",
           MEMORY_DEFAULT,
           lopts,
           &lopt
@@ -82,13 +94,11 @@ void IndexObject::New(const v8::FunctionCallbackInfo<v8::Value>& args) {
       isolate->ThrowException(
         v8::String::NewFromUtf8(isolate, "Unable to load index")
       );
-      delete prefix;
       return;
     }
     IndexObject* obj = new IndexObject(idx);
     obj->Wrap(args.This());
     args.GetReturnValue().Set(args.This());
-    delete prefix;
   } else {
     // Invoked as plain function `Index(...)`, turn into construct call.
     const int argc = 1;
@@ -102,13 +112,154 @@ void IndexObject::New(const v8::FunctionCallbackInfo<v8::Value>& args) {
   }
 }
 
-void IndexObject::PlusOne(const v8::FunctionCallbackInfo<v8::Value>& args) {
+void IndexObject::Search(const v8::FunctionCallbackInfo<v8::Value>& args) {
   v8::Isolate* isolate = args.GetIsolate();
 
-  IndexObject* obj = node::ObjectWrap::Unwrap<IndexObject>(args.Holder());
-  obj->value_ += 1;
+  v8::String::Utf8Value query(args[0]);
+  v8::String::Utf8Value optType(args[3]);
+  v8::Local<v8::Array> optArgsTuple;
+  if (args[4]->IsArray())
+    optArgsTuple = args[4].As<v8::Array>();
+  unsigned long startdoc = args[1]->IntegerValue();
+  unsigned long len = args[2]->IntegerValue();
+  IndexObject* Index = node::ObjectWrap::Unwrap<IndexObject>(args.Holder());
+  struct index_result* result;
+  unsigned int results;
+  double/*unsigned long int*/ total_results;
+  int est;
+  unsigned int accumulator_limit = args[5]->Uint32Value();
+  int opts = INDEX_SEARCH_NOOPT;
+  struct index_search_opt opt;
+
+  opt.u.okapi_k3.k1 = 1.2;
+  opt.u.okapi_k3.k3 = 1e10;
+  opt.u.okapi_k3.b = 0.75;
+
+  if (
+    (result = (struct index_result*)malloc(sizeof(*result) * len)) == NULL
+  ) {
+    isolate->ThrowException(
+      v8::String::NewFromUtf8(isolate, "Unable to allocate results")
+    );
+    return;
+  }
+  if (args[3]->IsString()) {
+    if (strcmp(*optType, "COSINE") == 0) {
+      opts = INDEX_SEARCH_COSINE_RANK;
+    } else if (strcmp(*optType, "OKAPI") == 0) {
+      opts = INDEX_SEARCH_OKAPI_RANK;
+    } else if (strcmp(*optType, "OKAPI_K3") == 0) {
+      if (optArgsTuple.IsEmpty()) {
+        isolate->ThrowException(
+          v8::String::NewFromUtf8(isolate, "Must supply args to search type")
+        );
+        free(result);
+        return;
+      }
+      opts = INDEX_SEARCH_OKAPI_RANK;
+      opt.u.okapi_k3.k1 = optArgsTuple->Get(0)->IntegerValue();
+      opt.u.okapi_k3.k3 = optArgsTuple->Get(1)->IntegerValue();
+      opt.u.okapi_k3.b = optArgsTuple->Get(2)->IntegerValue();
+    } else if (strcmp(*optType, "HAWKAPI") == 0) {
+      if (optArgsTuple.IsEmpty()) {
+        isolate->ThrowException(
+          v8::String::NewFromUtf8(isolate, "Must supply args to search type")
+        );
+        free(result);
+        return;
+      }
+      opts = INDEX_SEARCH_HAWKAPI_RANK;
+      opt.u.hawkapi.alpha = optArgsTuple->Get(0)->IntegerValue();
+      opt.u.hawkapi.k3 = optArgsTuple->Get(1)->IntegerValue();
+    } else if (strcmp(*optType, "DIRICHLET") == 0) {
+      opts = INDEX_SEARCH_DIRICHLET_RANK;
+      if (optArgsTuple.IsEmpty() || optArgsTuple->Length() == 0)
+        opt.u.dirichlet.mu = 2500.0;
+      else
+        opt.u.dirichlet.mu = optArgsTuple->Get(0)->NumberValue();
+    } else {
+      isolate->ThrowException(
+        v8::String::NewFromUtf8(isolate, "Unknown search type")
+      );
+      free(result);
+      return;
+    }
+  }
+  if (accumulator_limit != 0) {
+    opts |= INDEX_SEARCH_ACCUMULATOR_LIMIT;
+    opt.accumulator_limit = accumulator_limit;
+  }
+#if 1 /* Nick */
+ opts |= INDEX_SEARCH_SUMMARY_TYPE;
+ opt.summary_type = INDEX_SUMMARISE_CAPITALISE;
+#endif
+  if (!index_search(Index->idx, *query, startdoc, len,
+      result, &results, &total_results, &est, opts, &opt)) {
+    char err_buf[1024];
+    snprintf(err_buf, 1024, "Unable to perform search for query '%s'; "
+       "system error is '%s'\n", *query, strerror(errno));
+    isolate->ThrowException(
+      v8::String::NewFromUtf8(isolate, err_buf)
+    );
+    free(result);
+    return;
+  }
+  args.GetReturnValue().Set(
+    index_results_to_object(isolate, result, results, total_results)
+  );
+  free(result);
+  return;
+}
+
+static v8::Local<v8::Object> index_result_to_object(
+  v8::Isolate* isolate,
+  struct index_result* result
+) {
+  v8::EscapableHandleScope handle_scope(isolate);
+  v8::Local<v8::Object> result_object = v8::Object::New(isolate);
+  result_object->Set(
+    v8::String::NewFromUtf8(isolate, "docno"),
+    v8::Integer::New(isolate, result->docno)
+  );
+  result_object->Set(
+    v8::String::NewFromUtf8(isolate, "score"),
+    v8::Number::New(isolate, result->score)
+  );
+  result_object->Set(
+    v8::String::NewFromUtf8(isolate, "summary"),
+    v8::String::NewFromUtf8(isolate, result->summary)
+  );
+  result_object->Set(
+    v8::String::NewFromUtf8(isolate, "title"),
+    v8::String::NewFromUtf8(isolate, result->title)
+  );
+  result_object->Set(
+    v8::String::NewFromUtf8(isolate, "auxiliary"),
+    v8::String::NewFromUtf8(isolate, result->auxilliary)
+  );
+  return handle_scope.Escape(result_object);
+}
 
-  args.GetReturnValue().Set(v8::Number::New(isolate, obj->value_));
+static v8::Local<v8::Object> index_results_to_object(
+  v8::Isolate* isolate,
+  struct index_result* results,
+  unsigned int num_results,
+  double/*unsigned long int*/ total_results
+) {
+  v8::EscapableHandleScope handle_scope(isolate);
+  v8::Local<v8::Object> results_object = v8::Object::New(isolate);
+  v8::Local<v8::Array> results_array = v8::Array::New(isolate, num_results);
+  for (unsigned int i = 0; i < num_results; ++i)
+    results_array->Set(i, index_result_to_object(isolate, results + i));
+  results_object->Set(
+    v8::String::NewFromUtf8(isolate, "results"),
+    results_array
+  );
+  results_object->Set(
+    v8::String::NewFromUtf8(isolate, "total_results"),
+    v8::Number::New(isolate, total_results)
+  );
+  return handle_scope.Escape(results_object);
 }
 
 void InitAll(v8::Local<v8::Object> exports) {