#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() {
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(
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;
if (
(
idx = index_load(
- prefix ? **prefix : "index",
+ args[0]->IsString() ? *prefix : "index",
MEMORY_DEFAULT,
lopts,
&lopt
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;
}
}
-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) {