Skip to content

Commit 8c83b17

Browse files
committed
MLE-17147 Added annTopK support
1 parent 01e48e4 commit 8c83b17

File tree

8 files changed

+146
-4
lines changed

8 files changed

+146
-4
lines changed

lib/plan-builder-generated.js

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,13 @@
1515
*/
1616
'use strict';
1717

18-
/* IMPORTANT: Do not edit. This file is generated. */
18+
/*
19+
The contents of this file are mostly an output of the Optic code generator.
20+
But some parts have been manually modified. So care needs to be taken when
21+
running the code generator to not lose any manual modifications, each of
22+
which should either be commented or should be obvious, such as changes in
23+
version numbers for "since" annotations.
24+
*/
1925

2026
const types = require('./server-types-generated.js');
2127
const bldrbase = require('./plan-builder-base.js');
@@ -7470,6 +7476,28 @@ class PlanModifyPlan extends PlanPreparePlan {
74707476
constructor(prior, ns, fn, args) {
74717477
super(prior, ns, fn, args);
74727478
}
7479+
7480+
/**
7481+
* This method facilitates Approximate Nearest Neighbor vector search. It searches for K nearest neighbor vector embeddings that are stored in database given a query vector. Provides a client interface to a server function. See {@link http://docs.marklogic.com/ModifyPlan.prototype.annTopK|ModifyPlan.prototype.annTopK}
7482+
* @method planBuilder.ModifyPlan#annTopK
7483+
* @since 3.6.0
7484+
* @param { XsInt } [k] - This positive integer k is the top-K rows to return as a result of the index lookup.
7485+
* @param { PlanColumn } [vectorColumn] - The column representing the vector ann-indexed column to perform the index lookup against. The columns can be named with a string or a column parameter function such as op:col.
7486+
* @param { VecVector } [queryVector] - This specifies the query vector to perform the index lookup with.
7487+
* @param { PlanColumn } [distance] - The column is the output column that returns the values of the distance metric of the vectors retrieved from the index associated with vectorColumn and the qv. The columns can be named with a string or a column parameter function such as op.col.
7488+
* @param { XsFloat } [queryTolerance] - This specifies the query tolerance to help balance recall and search time. The value is between 0.0 and 1.0. At 0.0, the recall will be highest. At 1.0 the recall will likely see a large degradation, but queries will be quick. The default value is 0.0.
7489+
* @returns { planBuilder.ModifyPlan }
7490+
*/
7491+
annTopK(...args) {
7492+
const namer = bldrbase.getNamer(args, 'k');
7493+
const paramdefs = [['k', [types.XsInt], true, false], ['vector-column', [PlanColumn], true, false], ['query-vector', [types.VecVector], true, false], ['distance', [PlanColumn], false, false], ['query-tolerance', [types.XsFloat], false, false]];
7494+
const checkedArgs = (namer !== null) ?
7495+
bldrbase.makeNamedArgs(namer, 'PlanModifyPlan.annTopK', 3, new Set(['k', 'vector-column', 'query-vector', 'distance', 'query-tolerance']), paramdefs, args) :
7496+
bldrbase.makePositionalArgs('PlanModifyPlan.annTopK', 3, false, paramdefs, args);
7497+
return new PlanModifyPlan(this, 'op', 'ann-top-k', checkedArgs);
7498+
7499+
}
7500+
74737501
/**
74747502
* This function adds new columns or modifies existing columns based on expressions while preserving existing unmodified columns in the row set. Provides a client interface to a server function. See {@link http://docs.marklogic.com/ModifyPlan.prototype.bind|ModifyPlan.prototype.bind}
74757503
* @method planBuilder.ModifyPlan#bind

test-app/build.gradle

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,17 @@
11
// Only used for setting up the test AppServer in MarkLogic
22
plugins {
33
id 'net.saliman.properties' version '1.5.2'
4-
id "com.marklogic.ml-gradle" version "4.6.0"
4+
id "com.marklogic.ml-gradle" version "5.0.0"
55
}
6+
7+
tasks.register("addMarkLogic12SchemasIfNecessary", com.marklogic.gradle.task.MarkLogicTask) {
8+
description = "If testing against MarkLogic 12, include schemas that will not work on MarkLogic 11 or earlier."
9+
doLast {
10+
def version = new com.marklogic.mgmt.resource.clusters.ClusterManager(getManageClient()).getVersion()
11+
if (version.startsWith("12.")) {
12+
mlAppConfig.getSchemaPaths().add(new File(getProjectDir(), "src/main/ml-schemas-12").getAbsolutePath())
13+
}
14+
}
15+
}
16+
mlDeploy.dependsOn addMarkLogic12SchemasIfNecessary
17+
mlLoadSchemas.dependsOn addMarkLogic12SchemasIfNecessary

test-app/docker-compose.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
version: '1.0'
21
name: node-client
32

43
services:
54

65
marklogic:
7-
image: "marklogicdb/marklogic-db:11.1.0-centos-1.1.0"
6+
image: "progressofficial/marklogic-db:latest"
7+
# image: "ml-docker-db-dev-tierpoint.bed-artifactory.bedford.progress.com/marklogic/marklogic-server-ubi:latest-12"
88
platform: linux/amd64
99
environment:
1010
- INSTALL_CONVERTERS=true
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"person": {
3+
"name": "Alice",
4+
"summary": "About Alice",
5+
"embedding": [
6+
1.1,
7+
2.2,
8+
3.3
9+
]
10+
}
11+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"person": {
3+
"name": "Bob",
4+
"summary": "Below Bob",
5+
"embedding": [
6+
9.9,
7+
8.8,
8+
7.7
9+
]
10+
}
11+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
*=rest-reader,read,rest-writer,update
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<template xmlns="http://marklogic.com/xdmp/tde">
2+
<context>/person</context>
3+
<directories><directory>/optic/vectors/</directory></directories>
4+
<rows>
5+
<row>
6+
<schema-name>vectors</schema-name>
7+
<view-name>persons</view-name>
8+
<columns>
9+
<column>
10+
<name>name</name>
11+
<scalar-type>string</scalar-type>
12+
<val>name</val>
13+
</column>
14+
15+
<column>
16+
<name>summary</name>
17+
<scalar-type>string</scalar-type>
18+
<val>summary</val>
19+
</column>
20+
21+
<column>
22+
<name>embedding</name>
23+
<scalar-type>vector</scalar-type>
24+
<val>vec:vector(embedding)</val>
25+
<dimension>3</dimension>
26+
<invalid-values>reject</invalid-values>
27+
</column>
28+
</columns>
29+
</row>
30+
</rows>
31+
</template>

test-basic/annTopK.js

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* Copyright © 2024 MarkLogic Corporation. All Rights Reserved.
3+
*/
4+
'use strict';
5+
6+
const marklogic = require('../');
7+
const p = marklogic.planBuilder;
8+
9+
const pbb = require('./plan-builder-base');
10+
const assert = require('assert');
11+
const testlib = require('../etc/test-lib');
12+
let serverConfiguration = {};
13+
const execPlan = pbb.execPlan;
14+
15+
describe('tests for annTopK', function () {
16+
before(function (done) {
17+
try {
18+
testlib.findServerConfiguration(serverConfiguration);
19+
setTimeout(() => {
20+
if (serverConfiguration.serverVersion < 12) {
21+
this.skip();
22+
}
23+
done();
24+
}, 3000);
25+
} catch (error) {
26+
done(error);
27+
}
28+
});
29+
30+
it('happy path', function (done) {
31+
execPlan(p
32+
.fromView('vectors', 'persons', '')
33+
.annTopK(10, p.col('embedding'), p.vec.vector([1.1, 2.2, 3.3]), p.col('distance'), 0.5)
34+
.orderBy(p.col('name'))
35+
)
36+
.then(function (response) {
37+
const rows = response.rows;
38+
assert(rows.length === 2, 'Expecting both rows in the view to be returned.');
39+
assert(rows[0].name.value === 'Alice');
40+
assert(rows[0].distance.type === 'xs:float', 'Verifying that the distance column was populated.');
41+
assert(rows[1].name.value === 'Bob');
42+
assert(rows[1].distance.type === 'xs:float', 'Verifying that the distance column was populated.');
43+
done();
44+
})
45+
.catch(done);
46+
});
47+
48+
});

0 commit comments

Comments
 (0)