Skip to content

Commit

Permalink
Add: remove and contains for JS
Browse files Browse the repository at this point in the history
  • Loading branch information
ashvardanian committed Aug 5, 2023
1 parent fb8b3e0 commit be42532
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 2 deletions.
62 changes: 62 additions & 0 deletions javascript/lib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ class Index : public Napi::ObjectWrap<Index> {

void Add(Napi::CallbackInfo const& ctx);
Napi::Value Search(Napi::CallbackInfo const& ctx);
Napi::Value Remove(Napi::CallbackInfo const& ctx);
Napi::Value Contains(Napi::CallbackInfo const& ctx);

std::unique_ptr<index_dense_t> native_;
};
Expand All @@ -51,6 +53,8 @@ Napi::Object Index::Init(Napi::Env env, Napi::Object exports) {
InstanceMethod("connectivity", &Index::GetConnectivity),
InstanceMethod("add", &Index::Add),
InstanceMethod("search", &Index::Search),
InstanceMethod("remove", &Index::Remove),
InstanceMethod("contains", &Index::Contains),
InstanceMethod("save", &Index::Save),
InstanceMethod("load", &Index::Load),
InstanceMethod("view", &Index::View),
Expand Down Expand Up @@ -291,6 +295,64 @@ Napi::Value Index::Search(Napi::CallbackInfo const& ctx) {
}
}

Napi::Value Index::Remove(Napi::CallbackInfo const& ctx) {
Napi::Env env = ctx.Env();
if (ctx.Length() < 1 || !ctx[0].IsBigInt()) {
Napi::TypeError::New(env, "Expects an entry identifier").ThrowAsJavaScriptException();
return {};
}

Napi::BigInt key_js = ctx[0].As<Napi::BigInt>();
bool lossless = true;
std::uint64_t key = key_js.Uint64Value(&lossless);
if (!lossless) {
Napi::TypeError::New(env, "Identifier must be an unsigned integer").ThrowAsJavaScriptException();
return {};
}

try {
auto result = native_->remove(key);
if (!result) {
Napi::TypeError::New(env, "Removal has failed").ThrowAsJavaScriptException();
return {};
}
return Napi::Boolean::New(env, result.completed);
} catch (std::bad_alloc const&) {
Napi::TypeError::New(env, "Out of memory").ThrowAsJavaScriptException();
return {};
} catch (...) {
Napi::TypeError::New(env, "Search failed").ThrowAsJavaScriptException();
return {};
}
}

Napi::Value Index::Contains(Napi::CallbackInfo const& ctx) {
Napi::Env env = ctx.Env();
if (ctx.Length() < 1 || !ctx[0].IsBigInt()) {
Napi::TypeError::New(env, "Expects an entry identifier").ThrowAsJavaScriptException();
return {};
}

Napi::BigInt key_js = ctx[0].As<Napi::BigInt>();
bool lossless = true;
std::uint64_t key = key_js.Uint64Value(&lossless);
if (!lossless) {
Napi::TypeError::New(env, "Identifier must be an unsigned integer").ThrowAsJavaScriptException();
return {};
}

try {
bool result = native_->contains(key);
return Napi::Boolean::New(env, result);
} catch (std::bad_alloc const&) {
Napi::TypeError::New(env, "Out of memory").ThrowAsJavaScriptException();
return {};
} catch (...) {
Napi::TypeError::New(env, "Search failed").ThrowAsJavaScriptException();
return {};
}
}

Napi::Object InitAll(Napi::Env env, Napi::Object exports) { return Index::Init(env, exports); }

NODE_API_MODULE(usearch, InitAll)
1 change: 1 addition & 0 deletions javascript/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ assert.equal(index.size(), 0n, 'initial size should be 0');
index.add(15n, new Float32Array([10, 20]));
index.add(16n, new Float32Array([10, 25]));
assert.equal(index.size(), 2n, 'size after adding elements should be 2');
assert.equal(index.contains(15n), true, 'entry must be present after insertion');

var results = index.search(new Float32Array([13, 14]), 2n);
assert.deepEqual(results.keys, new BigUint64Array([15n, 16n]), 'keys should be 15 and 16');
Expand Down
19 changes: 17 additions & 2 deletions javascript/usearch.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export interface Matches {

/** K-Approximate Nearest Neighbors search index. */
export class Index {

/**
* Constructs a new index.
*
Expand Down Expand Up @@ -42,7 +42,7 @@ export class Index {
* @return {bigints} The capacity of index.
*/
capacity(): bigint;

/**
* Returns connectivity.
* @return {bigint} The connectivity of index.
Expand Down Expand Up @@ -84,4 +84,19 @@ export class Index {
* @return {Matches} Output of the search result.
*/
search(mat: Float32Array, k: bigint): Matches;

/**
* Check if an entry is contained in the index.
*
* @param {bigint} key Identifier to look up.
*/
contains(key: bigint): boolean;

/**
* Remove a vector from the index.
*
* @param {bigint} key Input identifier for every vector to be removed.
*/
remove(key: bigint): boolean;

}

0 comments on commit be42532

Please sign in to comment.