This is an automated email from the ASF dual-hosted git repository.

spmallette pushed a commit to branch TINKERPOP-3158
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git

commit 2c178e9144a0a8d017df69620601e0fb0f6010b1
Author: Stephen Mallette <[email protected]>
AuthorDate: Tue May 6 10:59:07 2025 -0400

    Add ServiceRegistry for vector search with call()
---
 .../gremlin/structure/service/ServiceRegistry.java |   3 +-
 .../Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs |  22 +--
 gremlin-go/driver/cucumber/gremlin.go              |  22 +--
 .../gremlin-javascript/test/cucumber/gremlin.js    |  22 +--
 gremlin-python/src/main/python/radish/gremlin.py   |  22 +--
 .../gremlin/test/features/map/Call.feature         |  38 ++---
 .../services/TinkerVectorSearchFactory.java        |  39 +++--
 .../tinkergraph/structure/AbstractTinkerIndex.java |   2 +-
 .../structure/AbstractTinkerVectorIndex.java       |   2 +-
 .../gremlin/tinkergraph/structure/TinkerGraph.java |   1 -
 .../tinkergraph/structure/TinkerIndexElement.java  |   5 +
 .../structure/TinkerGraphServiceTest.java          | 184 ++++++++++++++++++---
 12 files changed, 262 insertions(+), 100 deletions(-)

diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/service/ServiceRegistry.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/service/ServiceRegistry.java
index aae9bed8bf..83faccb1e2 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/service/ServiceRegistry.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/service/ServiceRegistry.java
@@ -25,7 +25,6 @@ import 
org.apache.tinkerpop.gremlin.structure.util.CloseableIterator;
 import org.apache.tinkerpop.shaded.jackson.core.JsonProcessingException;
 import org.apache.tinkerpop.shaded.jackson.databind.ObjectMapper;
 
-import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.Objects;
@@ -87,7 +86,7 @@ public class ServiceRegistry implements DirectoryService, 
AutoCloseable {
      * {@link DirectoryService} execution. List or describe the registered 
callable services.
      */
     @Override
-    public CloseableIterator execute(ServiceCallContext ctx, final Map params) 
{
+    public CloseableIterator execute(final ServiceCallContext ctx, final Map 
params) {
         final boolean verbose = (boolean) params.getOrDefault(Params.VERBOSE, 
false);
         final String serviceName = (String) params.get(Params.SERVICE);
 
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs 
b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
index 774cd7043c..c44f70ae56 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
@@ -634,18 +634,18 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
                
{"g_V_hasLabelXpersonX_valuesXageX_asString_concatX_years_oldX", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.V().HasLabel("person").Values<object>("age").AsString().Concat(" 
years old")}}, 
                {"g_call", new List<Func<GraphTraversalSource, 
IDictionary<string, object>, ITraversal>> {(g,p) =>g.Call<object>()}}, 
                {"g_callXlistX", new List<Func<GraphTraversalSource, 
IDictionary<string, object>, ITraversal>> {(g,p) =>g.Call<object>((string) 
"--list")}}, 
-               {"g_callXlistX_withXstring_stringX", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.Call<object>((string) "--list").With("service", "tinker.search")}}, 
-               {"g_callXlistX_withXstring_traversalX", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.Call<object>((string) "--list").With("service", 
__.Constant<object>("tinker.search"))}}, 
+               {"g_callXlistX_withXstring_stringX", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.Call<object>((string) "--list").With("service", 
"tinker.search.text")}}, 
+               {"g_callXlistX_withXstring_traversalX", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.Call<object>((string) "--list").With("service", 
__.Constant<object>("tinker.search.text"))}}, 
                {"g_callXlist_mapX", new List<Func<GraphTraversalSource, 
IDictionary<string, object>, ITraversal>> {(g,p) =>g.Call<object>("--list", 
(IDictionary<object, object>) p["xx1"])}}, 
-               {"g_callXlist_traversalX", new List<Func<GraphTraversalSource, 
IDictionary<string, object>, ITraversal>> {(g,p) =>g.Call<object>("--list", 
(ITraversal) 
__.Project<object>("service").By(__.Constant<object>("tinker.search")))}}, 
-               {"g_callXlist_map_traversalX", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.Call<object>("--list", (IDictionary<object, object>) p["xx1"], 
(ITraversal) 
__.Project<object>("service").By(__.Constant<object>("tinker.search")))}}, 
-               {"g_callXsearch_mapX", new List<Func<GraphTraversalSource, 
IDictionary<string, object>, ITraversal>> {(g,p) 
=>g.Call<object>("tinker.search", (IDictionary<object, object>) 
p["xx1"]).Element()}}, 
-               {"g_callXsearch_traversalX", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.Call<object>("tinker.search", (ITraversal) 
__.Project<object>("search").By(__.Constant<object>("vada"))).Element()}}, 
-               {"g_callXsearchX_withXstring_stringX", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.Call<object>((string) "tinker.search").With("search", 
"vada").Element()}}, 
-               {"g_callXsearchX_withXstring_traversalX", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.Call<object>((string) "tinker.search").With("search", 
__.Constant<object>("vada")).Element()}}, 
-               {"g_callXsearch_mapX_withXstring_VertexX", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.Call<object>("tinker.search", (IDictionary<object, object>) 
p["xx1"]).With("type", "Vertex").Element()}}, 
-               {"g_callXsearch_mapX_withXstring_EdgeX", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.Call<object>("tinker.search", (IDictionary<object, object>) 
p["xx1"]).With("type", "Edge").Element()}}, 
-               {"g_callXsearch_mapX_withXstring_VertexPropertyX", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.Call<object>("tinker.search", (IDictionary<object, object>) 
p["xx1"]).With("type", "VertexProperty").Element()}}, 
+               {"g_callXlist_traversalX", new List<Func<GraphTraversalSource, 
IDictionary<string, object>, ITraversal>> {(g,p) =>g.Call<object>("--list", 
(ITraversal) 
__.Project<object>("service").By(__.Constant<object>("tinker.search.text")))}}, 
+               {"g_callXlist_map_traversalX", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.Call<object>("--list", (IDictionary<object, object>) p["xx1"], 
(ITraversal) 
__.Project<object>("service").By(__.Constant<object>("tinker.search.text")))}}, 
+               {"g_callXsearch_mapX", new List<Func<GraphTraversalSource, 
IDictionary<string, object>, ITraversal>> {(g,p) 
=>g.Call<object>("tinker.search.text", (IDictionary<object, object>) 
p["xx1"]).Element()}}, 
+               {"g_callXsearch_traversalX", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.Call<object>("tinker.search.text", (ITraversal) 
__.Project<object>("search").By(__.Constant<object>("vada"))).Element()}}, 
+               {"g_callXsearchX_withXstring_stringX", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.Call<object>((string) "tinker.search.text").With("search", 
"vada").Element()}}, 
+               {"g_callXsearchX_withXstring_traversalX", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.Call<object>((string) "tinker.search.text").With("search", 
__.Constant<object>("vada")).Element()}}, 
+               {"g_callXsearch_mapX_withXstring_VertexX", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.Call<object>("tinker.search.text", (IDictionary<object, object>) 
p["xx1"]).With("type", "Vertex").Element()}}, 
+               {"g_callXsearch_mapX_withXstring_EdgeX", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.Call<object>("tinker.search.text", (IDictionary<object, object>) 
p["xx1"]).With("type", "Edge").Element()}}, 
+               {"g_callXsearch_mapX_withXstring_VertexPropertyX", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.Call<object>("tinker.search.text", (IDictionary<object, object>) 
p["xx1"]).With("type", "VertexProperty").Element()}}, 
                {"g_V_callXdcX", new List<Func<GraphTraversalSource, 
IDictionary<string, object>, ITraversal>> {(g,p) 
=>g.V().As("v").Call<object>((string) 
"tinker.degree.centrality").Project<object>("vertex", 
"degree").By(__.Select<object>("v")).By()}}, 
                {"g_V_whereXcallXdcXX", new List<Func<GraphTraversalSource, 
IDictionary<string, object>, ITraversal>> {(g,p) 
=>g.V().Where(__.Call<object>((string) "tinker.degree.centrality").Is(3))}}, 
                {"g_V_callXdcX_withXdirection_OUTX", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.V().As("v").Call<object>((string) 
"tinker.degree.centrality").With("direction", 
Direction.Out).Project<object>("vertex", 
"degree").By(__.Select<object>("v")).By()}}, 
diff --git a/gremlin-go/driver/cucumber/gremlin.go 
b/gremlin-go/driver/cucumber/gremlin.go
index 17ec0da51c..8796f5f315 100644
--- a/gremlin-go/driver/cucumber/gremlin.go
+++ b/gremlin-go/driver/cucumber/gremlin.go
@@ -603,18 +603,18 @@ var translationMap = map[string][]func(g 
*gremlingo.GraphTraversalSource, p map[
     "g_V_hasLabelXpersonX_valuesXageX_asString_concatX_years_oldX": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return 
g.V().HasLabel("person").Values("age").AsString().Concat(" years old")}}, 
     "g_call": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return g.Call()}}, 
     "g_callXlistX": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return g.Call("--list")}}, 
-    "g_callXlistX_withXstring_stringX": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return g.Call("--list").With("service", 
"tinker.search")}}, 
-    "g_callXlistX_withXstring_traversalX": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return g.Call("--list").With("service", 
gremlingo.T__.Constant("tinker.search"))}}, 
+    "g_callXlistX_withXstring_stringX": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return g.Call("--list").With("service", 
"tinker.search.text")}}, 
+    "g_callXlistX_withXstring_traversalX": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return g.Call("--list").With("service", 
gremlingo.T__.Constant("tinker.search.text"))}}, 
     "g_callXlist_mapX": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return g.Call("--list", 
p["xx1"])}}, 
-    "g_callXlist_traversalX": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return g.Call("--list", 
gremlingo.T__.Project("service").By(gremlingo.T__.Constant("tinker.search")))}},
 
-    "g_callXlist_map_traversalX": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return g.Call("--list", 
p["xx1"], 
gremlingo.T__.Project("service").By(gremlingo.T__.Constant("tinker.search")))}},
 
-    "g_callXsearch_mapX": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return 
g.Call("tinker.search", p["xx1"]).Element()}}, 
-    "g_callXsearch_traversalX": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return 
g.Call("tinker.search", 
gremlingo.T__.Project("search").By(gremlingo.T__.Constant("vada"))).Element()}},
 
-    "g_callXsearchX_withXstring_stringX": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return g.Call("tinker.search").With("search", 
"vada").Element()}}, 
-    "g_callXsearchX_withXstring_traversalX": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return g.Call("tinker.search").With("search", 
gremlingo.T__.Constant("vada")).Element()}}, 
-    "g_callXsearch_mapX_withXstring_VertexX": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return g.Call("tinker.search", 
p["xx1"]).With("type", "Vertex").Element()}}, 
-    "g_callXsearch_mapX_withXstring_EdgeX": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return g.Call("tinker.search", 
p["xx1"]).With("type", "Edge").Element()}}, 
-    "g_callXsearch_mapX_withXstring_VertexPropertyX": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return g.Call("tinker.search", 
p["xx1"]).With("type", "VertexProperty").Element()}}, 
+    "g_callXlist_traversalX": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return g.Call("--list", 
gremlingo.T__.Project("service").By(gremlingo.T__.Constant("tinker.search.text")))}},
 
+    "g_callXlist_map_traversalX": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return g.Call("--list", 
p["xx1"], 
gremlingo.T__.Project("service").By(gremlingo.T__.Constant("tinker.search.text")))}},
 
+    "g_callXsearch_mapX": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return 
g.Call("tinker.search.text", p["xx1"]).Element()}}, 
+    "g_callXsearch_traversalX": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return 
g.Call("tinker.search.text", 
gremlingo.T__.Project("search").By(gremlingo.T__.Constant("vada"))).Element()}},
 
+    "g_callXsearchX_withXstring_stringX": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return g.Call("tinker.search.text").With("search", 
"vada").Element()}}, 
+    "g_callXsearchX_withXstring_traversalX": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return g.Call("tinker.search.text").With("search", 
gremlingo.T__.Constant("vada")).Element()}}, 
+    "g_callXsearch_mapX_withXstring_VertexX": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return g.Call("tinker.search.text", 
p["xx1"]).With("type", "Vertex").Element()}}, 
+    "g_callXsearch_mapX_withXstring_EdgeX": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return g.Call("tinker.search.text", 
p["xx1"]).With("type", "Edge").Element()}}, 
+    "g_callXsearch_mapX_withXstring_VertexPropertyX": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return g.Call("tinker.search.text", 
p["xx1"]).With("type", "VertexProperty").Element()}}, 
     "g_V_callXdcX": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return 
g.V().As("v").Call("tinker.degree.centrality").Project("vertex", 
"degree").By(gremlingo.T__.Select("v")).By()}}, 
     "g_V_whereXcallXdcXX": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return 
g.V().Where(gremlingo.T__.Call("tinker.degree.centrality").Is(3))}}, 
     "g_V_callXdcX_withXdirection_OUTX": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return 
g.V().As("v").Call("tinker.degree.centrality").With("direction", 
gremlingo.Direction.Out).Project("vertex", 
"degree").By(gremlingo.T__.Select("v")).By()}}, 
diff --git 
a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js
 
b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js
index c261f4f92d..b49f5a43aa 100644
--- 
a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js
+++ 
b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js
@@ -633,18 +633,18 @@ const gremlins = {
     g_V_hasLabelXpersonX_valuesXageX_asString_concatX_years_oldX: 
[function({g}) { return 
g.V().hasLabel("person").values("age").asString().concat(" years old") }], 
     g_call: [function({g}) { return g.call() }], 
     g_callXlistX: [function({g}) { return g.call("--list") }], 
-    g_callXlistX_withXstring_stringX: [function({g}) { return 
g.call("--list").with_("service", "tinker.search") }], 
-    g_callXlistX_withXstring_traversalX: [function({g}) { return 
g.call("--list").with_("service", __.constant("tinker.search")) }], 
+    g_callXlistX_withXstring_stringX: [function({g}) { return 
g.call("--list").with_("service", "tinker.search.text") }], 
+    g_callXlistX_withXstring_traversalX: [function({g}) { return 
g.call("--list").with_("service", __.constant("tinker.search.text")) }], 
     g_callXlist_mapX: [function({g, xx1}) { return g.call("--list", xx1) }], 
-    g_callXlist_traversalX: [function({g}) { return g.call("--list", 
__.project("service").by(__.constant("tinker.search"))) }], 
-    g_callXlist_map_traversalX: [function({g, xx1}) { return g.call("--list", 
xx1, __.project("service").by(__.constant("tinker.search"))) }], 
-    g_callXsearch_mapX: [function({g, xx1}) { return g.call("tinker.search", 
xx1).element() }], 
-    g_callXsearch_traversalX: [function({g}) { return g.call("tinker.search", 
__.project("search").by(__.constant("vada"))).element() }], 
-    g_callXsearchX_withXstring_stringX: [function({g}) { return 
g.call("tinker.search").with_("search", "vada").element() }], 
-    g_callXsearchX_withXstring_traversalX: [function({g}) { return 
g.call("tinker.search").with_("search", __.constant("vada")).element() }], 
-    g_callXsearch_mapX_withXstring_VertexX: [function({g, xx1}) { return 
g.call("tinker.search", xx1).with_("type", "Vertex").element() }], 
-    g_callXsearch_mapX_withXstring_EdgeX: [function({g, xx1}) { return 
g.call("tinker.search", xx1).with_("type", "Edge").element() }], 
-    g_callXsearch_mapX_withXstring_VertexPropertyX: [function({g, xx1}) { 
return g.call("tinker.search", xx1).with_("type", "VertexProperty").element() 
}], 
+    g_callXlist_traversalX: [function({g}) { return g.call("--list", 
__.project("service").by(__.constant("tinker.search.text"))) }], 
+    g_callXlist_map_traversalX: [function({g, xx1}) { return g.call("--list", 
xx1, __.project("service").by(__.constant("tinker.search.text"))) }], 
+    g_callXsearch_mapX: [function({g, xx1}) { return 
g.call("tinker.search.text", xx1).element() }], 
+    g_callXsearch_traversalX: [function({g}) { return 
g.call("tinker.search.text", 
__.project("search").by(__.constant("vada"))).element() }], 
+    g_callXsearchX_withXstring_stringX: [function({g}) { return 
g.call("tinker.search.text").with_("search", "vada").element() }], 
+    g_callXsearchX_withXstring_traversalX: [function({g}) { return 
g.call("tinker.search.text").with_("search", __.constant("vada")).element() }], 
+    g_callXsearch_mapX_withXstring_VertexX: [function({g, xx1}) { return 
g.call("tinker.search.text", xx1).with_("type", "Vertex").element() }], 
+    g_callXsearch_mapX_withXstring_EdgeX: [function({g, xx1}) { return 
g.call("tinker.search.text", xx1).with_("type", "Edge").element() }], 
+    g_callXsearch_mapX_withXstring_VertexPropertyX: [function({g, xx1}) { 
return g.call("tinker.search.text", xx1).with_("type", 
"VertexProperty").element() }], 
     g_V_callXdcX: [function({g}) { return 
g.V().as("v").call("tinker.degree.centrality").project("vertex", 
"degree").by(__.select("v")).by() }], 
     g_V_whereXcallXdcXX: [function({g}) { return 
g.V().where(__.call("tinker.degree.centrality").is(3)) }], 
     g_V_callXdcX_withXdirection_OUTX: [function({g}) { return 
g.V().as("v").call("tinker.degree.centrality").with_("direction", 
Direction.OUT).project("vertex", "degree").by(__.select("v")).by() }], 
diff --git a/gremlin-python/src/main/python/radish/gremlin.py 
b/gremlin-python/src/main/python/radish/gremlin.py
index 4985d650bc..bf3a144b73 100644
--- a/gremlin-python/src/main/python/radish/gremlin.py
+++ b/gremlin-python/src/main/python/radish/gremlin.py
@@ -606,18 +606,18 @@ world.gremlins = {
     'g_V_hasLabelXpersonX_valuesXageX_asString_concatX_years_oldX': [(lambda 
g:g.V().has_label('person').values('age').as_string().concat(' years old'))], 
     'g_call': [(lambda g:g.call())], 
     'g_callXlistX': [(lambda g:g.call('--list'))], 
-    'g_callXlistX_withXstring_stringX': [(lambda 
g:g.call('--list').with_('service', 'tinker.search'))], 
-    'g_callXlistX_withXstring_traversalX': [(lambda 
g:g.call('--list').with_('service', __.constant('tinker.search')))], 
+    'g_callXlistX_withXstring_stringX': [(lambda 
g:g.call('--list').with_('service', 'tinker.search.text'))], 
+    'g_callXlistX_withXstring_traversalX': [(lambda 
g:g.call('--list').with_('service', __.constant('tinker.search.text')))], 
     'g_callXlist_mapX': [(lambda g, xx1=None:g.call('--list', xx1))], 
-    'g_callXlist_traversalX': [(lambda g:g.call('--list', 
__.project('service').by(__.constant('tinker.search'))))], 
-    'g_callXlist_map_traversalX': [(lambda g, xx1=None:g.call('--list', xx1, 
__.project('service').by(__.constant('tinker.search'))))], 
-    'g_callXsearch_mapX': [(lambda g, xx1=None:g.call('tinker.search', 
xx1).element())], 
-    'g_callXsearch_traversalX': [(lambda g:g.call('tinker.search', 
__.project('search').by(__.constant('vada'))).element())], 
-    'g_callXsearchX_withXstring_stringX': [(lambda 
g:g.call('tinker.search').with_('search', 'vada').element())], 
-    'g_callXsearchX_withXstring_traversalX': [(lambda 
g:g.call('tinker.search').with_('search', __.constant('vada')).element())], 
-    'g_callXsearch_mapX_withXstring_VertexX': [(lambda g, 
xx1=None:g.call('tinker.search', xx1).with_('type', 'Vertex').element())], 
-    'g_callXsearch_mapX_withXstring_EdgeX': [(lambda g, 
xx1=None:g.call('tinker.search', xx1).with_('type', 'Edge').element())], 
-    'g_callXsearch_mapX_withXstring_VertexPropertyX': [(lambda g, 
xx1=None:g.call('tinker.search', xx1).with_('type', 
'VertexProperty').element())], 
+    'g_callXlist_traversalX': [(lambda g:g.call('--list', 
__.project('service').by(__.constant('tinker.search.text'))))], 
+    'g_callXlist_map_traversalX': [(lambda g, xx1=None:g.call('--list', xx1, 
__.project('service').by(__.constant('tinker.search.text'))))], 
+    'g_callXsearch_mapX': [(lambda g, xx1=None:g.call('tinker.search.text', 
xx1).element())], 
+    'g_callXsearch_traversalX': [(lambda g:g.call('tinker.search.text', 
__.project('search').by(__.constant('vada'))).element())], 
+    'g_callXsearchX_withXstring_stringX': [(lambda 
g:g.call('tinker.search.text').with_('search', 'vada').element())], 
+    'g_callXsearchX_withXstring_traversalX': [(lambda 
g:g.call('tinker.search.text').with_('search', 
__.constant('vada')).element())], 
+    'g_callXsearch_mapX_withXstring_VertexX': [(lambda g, 
xx1=None:g.call('tinker.search.text', xx1).with_('type', 'Vertex').element())], 
+    'g_callXsearch_mapX_withXstring_EdgeX': [(lambda g, 
xx1=None:g.call('tinker.search.text', xx1).with_('type', 'Edge').element())], 
+    'g_callXsearch_mapX_withXstring_VertexPropertyX': [(lambda g, 
xx1=None:g.call('tinker.search.text', xx1).with_('type', 
'VertexProperty').element())], 
     'g_V_callXdcX': [(lambda 
g:g.V().as_('v').call('tinker.degree.centrality').project('vertex', 
'degree').by(__.select('v')).by())], 
     'g_V_whereXcallXdcXX': [(lambda 
g:g.V().where(__.call('tinker.degree.centrality').is_(3)))], 
     'g_V_callXdcX_withXdirection_OUTX': [(lambda 
g:g.V().as_('v').call('tinker.degree.centrality').with_('direction', 
Direction.OUT).project('vertex', 'degree').by(__.select('v')).by())], 
diff --git 
a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Call.feature
 
b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Call.feature
index 0c44d7e952..ce80e6f425 100644
--- 
a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Call.feature
+++ 
b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Call.feature
@@ -27,7 +27,7 @@ Feature: Step - call()
     When iterated to list
     Then the result should be unordered
       | result |
-      | tinker.search |
+      | tinker.search.text |
       | tinker.degree.centrality |
 
   Scenario: g_callXlistX
@@ -39,34 +39,34 @@ Feature: Step - call()
     When iterated to list
     Then the result should be unordered
       | result |
-      | tinker.search |
+      | tinker.search.text |
       | tinker.degree.centrality |
 
   Scenario: g_callXlistX_withXstring_stringX
     Given the empty graph
     And the traversal of
       """
-      g.call("--list").with("service", "tinker.search")
+      g.call("--list").with("service", "tinker.search.text")
       """
     When iterated to list
     Then the result should be unordered
       | result |
-      | tinker.search |
+      | tinker.search.text |
 
   Scenario: g_callXlistX_withXstring_traversalX
     Given the empty graph
     And the traversal of
       """
-      g.call("--list").with("service", __.constant("tinker.search"))
+      g.call("--list").with("service", __.constant("tinker.search.text"))
       """
     When iterated to list
     Then the result should be unordered
       | result |
-      | tinker.search |
+      | tinker.search.text |
 
   Scenario: g_callXlist_mapX
     Given the empty graph
-    And using the parameter xx1 defined as "m[{\"service\": 
\"tinker.search\"}]"
+    And using the parameter xx1 defined as "m[{\"service\": 
\"tinker.search.text\"}]"
     And the traversal of
       """
       g.call("--list", xx1)
@@ -74,37 +74,37 @@ Feature: Step - call()
     When iterated to list
     Then the result should be unordered
       | result |
-      | tinker.search |
+      | tinker.search.text |
 
   Scenario: g_callXlist_traversalX
     Given the empty graph
     And the traversal of
       """
-      g.call("--list", __.project("service").by(__.constant("tinker.search")))
+      g.call("--list", 
__.project("service").by(__.constant("tinker.search.text")))
       """
     When iterated to list
     Then the result should be unordered
       | result |
-      | tinker.search |
+      | tinker.search.text |
 
   Scenario: g_callXlist_map_traversalX
     Given the empty graph
     And using the parameter xx1 defined as "m[{\"x\": \"y\"}]"
     And the traversal of
       """
-      g.call("--list", xx1, 
__.project("service").by(__.constant("tinker.search")))
+      g.call("--list", xx1, 
__.project("service").by(__.constant("tinker.search.text")))
       """
     When iterated to list
     Then the result should be unordered
       | result |
-      | tinker.search |
+      | tinker.search.text |
 
   Scenario: g_callXsearch_mapX
     Given the modern graph
     And using the parameter xx1 defined as "m[{\"search\": \"mar\"}]"
     And the traversal of
       """
-      g.call("tinker.search", xx1).element()
+      g.call("tinker.search.text", xx1).element()
       """
     When iterated to list
     Then the result should be unordered
@@ -115,7 +115,7 @@ Feature: Step - call()
     Given the modern graph
     And the traversal of
       """
-      g.call("tinker.search", 
__.project("search").by(__.constant("vada"))).element()
+      g.call("tinker.search.text", 
__.project("search").by(__.constant("vada"))).element()
       """
     When iterated to list
     Then the result should be unordered
@@ -126,7 +126,7 @@ Feature: Step - call()
     Given the modern graph
     And the traversal of
       """
-      g.call("tinker.search").with("search", "vada").element()
+      g.call("tinker.search.text").with("search", "vada").element()
       """
     When iterated to list
     Then the result should be unordered
@@ -137,7 +137,7 @@ Feature: Step - call()
     Given the modern graph
     And the traversal of
       """
-      g.call("tinker.search").with("search", __.constant("vada")).element()
+      g.call("tinker.search.text").with("search", 
__.constant("vada")).element()
       """
     When iterated to list
     Then the result should be unordered
@@ -149,7 +149,7 @@ Feature: Step - call()
     And using the parameter xx1 defined as "m[{\"search\": \"mar\"}]"
     And the traversal of
       """
-      g.call("tinker.search", xx1).with("type", "Vertex").element()
+      g.call("tinker.search.text", xx1).with("type", "Vertex").element()
       """
     When iterated to list
     Then the result should be unordered
@@ -161,7 +161,7 @@ Feature: Step - call()
     And using the parameter xx1 defined as "m[{\"search\": \"mar\"}]"
     And the traversal of
       """
-      g.call("tinker.search", xx1).with("type", "Edge").element()
+      g.call("tinker.search.text", xx1).with("type", "Edge").element()
       """
     When iterated to list
     Then the result should be empty
@@ -171,7 +171,7 @@ Feature: Step - call()
     And using the parameter xx1 defined as "m[{\"search\": \"mar\"}]"
     And the traversal of
       """
-      g.call("tinker.search", xx1).with("type", "VertexProperty").element()
+      g.call("tinker.search.text", xx1).with("type", 
"VertexProperty").element()
       """
     When iterated to list
     Then the result should be empty
diff --git 
a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/services/TinkerVectorSearchFactory.java
 
b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/services/TinkerVectorSearchFactory.java
index fb0b3c76f4..b0a793a814 100644
--- 
a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/services/TinkerVectorSearchFactory.java
+++ 
b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/services/TinkerVectorSearchFactory.java
@@ -19,37 +19,28 @@
 package org.apache.tinkerpop.gremlin.tinkergraph.services;
 
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
-import org.apache.tinkerpop.gremlin.structure.Direction;
 import org.apache.tinkerpop.gremlin.structure.Edge;
 import org.apache.tinkerpop.gremlin.structure.Element;
-import org.apache.tinkerpop.gremlin.structure.Property;
 import org.apache.tinkerpop.gremlin.structure.Vertex;
-import org.apache.tinkerpop.gremlin.structure.VertexProperty;
 import org.apache.tinkerpop.gremlin.structure.service.Service;
 import org.apache.tinkerpop.gremlin.structure.util.CloseableIterator;
 import org.apache.tinkerpop.gremlin.tinkergraph.structure.AbstractTinkerGraph;
-import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerHelper;
 import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIndexElement;
-import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
 
 import java.util.Collections;
-import java.util.Iterator;
 import java.util.Map;
-import java.util.Optional;
 import java.util.Set;
-import java.util.stream.Collectors;
-import java.util.stream.LongStream;
 
 import static 
org.apache.tinkerpop.gremlin.tinkergraph.services.TinkerVectorSearchFactory.Params.KEY;
 import static 
org.apache.tinkerpop.gremlin.tinkergraph.services.TinkerVectorSearchFactory.Params.TOP_K;
 import static org.apache.tinkerpop.gremlin.util.CollectionUtil.asMap;
 
 /**
- *
+ * Service to utilize a {@code TinkerVertexIndex} to do a vector search.
  */
 public class TinkerVectorSearchFactory extends 
TinkerServiceRegistry.TinkerServiceFactory<Element, Map<String, Object>> 
implements Service<Element, Map<String, Object>> {
 
-    public static final String NAME = "tinker.search.vector.topKByVertex";
+    public static final String NAME = "tinker.search.vector.topKByElement";
 
     public interface Params {
         /**
@@ -91,16 +82,38 @@ public class TinkerVectorSearchFactory extends 
TinkerServiceRegistry.TinkerServi
         if (isStart) {
             throw new 
UnsupportedOperationException(Exceptions.cannotStartTraversal);
         }
+
+        if (!params.containsKey(KEY)) {
+            throw new IllegalArgumentException("The parameter map must contain 
the key where the embedding is: " + KEY);
+        }
+
         return this;
     }
 
     @Override
     public CloseableIterator<Map<String,Object>> execute(final 
ServiceCallContext ctx, final Traverser.Admin<Element> in, final Map params) {
         final String key = (String) params.get(KEY);
-        final int k = (int) params.getOrDefault(TOP_K, 10);
+
+        // add 1 because we always filter 1 out of the index because it will 
return a match on itself
+        final int k = (int) params.getOrDefault(TOP_K, 10) + 1;
         final Element e = in.get();
+
+        // if the current element does not have the specified key, then return 
no results
+        if (!e.keys().contains(key))
+            return CloseableIterator.empty();
+
         final float[] embedding = e.value(key);
-        return CloseableIterator.of(graph.findNearestVertices(key, embedding, 
k).stream().map(TinkerIndexElement::toMap).iterator());
+        if (e instanceof Vertex) {
+            return CloseableIterator.of(graph.findNearestVertices(key, 
embedding, k).stream()
+                    .filter(tie -> !tie.getElement().equals(e))
+                    .map(TinkerIndexElement::toMap).iterator());
+        } else if (e instanceof Edge) {
+            return CloseableIterator.of(graph.findNearestEdges(key, embedding, 
k).stream()
+                    .filter(tie -> !tie.getElement().equals(e))
+                    .map(TinkerIndexElement::toMap).iterator());
+        } else {
+            return CloseableIterator.empty();
+        }
     }
 
     @Override
diff --git 
a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/AbstractTinkerIndex.java
 
b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/AbstractTinkerIndex.java
index a1460d9fde..e0295e2599 100644
--- 
a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/AbstractTinkerIndex.java
+++ 
b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/AbstractTinkerIndex.java
@@ -34,7 +34,7 @@ import java.util.Set;
  *
  * @author Valentyn Kahamlyk
  */
-public abstract class AbstractTinkerIndex<T extends Element> {
+abstract class AbstractTinkerIndex<T extends Element> {
 
     protected final Class<T> indexClass;
     protected final AbstractTinkerGraph graph;
diff --git 
a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/AbstractTinkerVectorIndex.java
 
b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/AbstractTinkerVectorIndex.java
index 7826d402e8..9141513daf 100644
--- 
a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/AbstractTinkerVectorIndex.java
+++ 
b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/AbstractTinkerVectorIndex.java
@@ -27,7 +27,7 @@ import java.util.List;
  *
  * @param <T> the type of elements stored in the vector index
  */
-public abstract class AbstractTinkerVectorIndex<T extends Element> extends 
AbstractTinkerIndex<T> {
+abstract class AbstractTinkerVectorIndex<T extends Element> extends 
AbstractTinkerIndex<T> {
     /**
      * Default number of nearest neighbors to return
      */
diff --git 
a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraph.java
 
b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraph.java
index 444fa74ecd..f26a386e3a 100644
--- 
a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraph.java
+++ 
b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraph.java
@@ -99,7 +99,6 @@ public class TinkerGraph extends AbstractTinkerGraph {
         if (graphLocation != null) loadGraph();
 
         serviceRegistry = new TinkerServiceRegistry(this);
-        serviceRegistry.registerService(new TinkerServiceRegistry(this));
         configuration.getList(String.class, GREMLIN_TINKERGRAPH_SERVICE, 
Collections.emptyList()).forEach(serviceClass ->
                 serviceRegistry.registerService(instantiate(serviceClass)));
     }
diff --git 
a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerIndexElement.java
 
b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerIndexElement.java
index d8e43afb4c..24fb22d144 100644
--- 
a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerIndexElement.java
+++ 
b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerIndexElement.java
@@ -18,9 +18,14 @@
  */
 package org.apache.tinkerpop.gremlin.tinkergraph.structure;
 
+import org.apache.tinkerpop.gremlin.structure.Element;
+
 import java.util.HashMap;
 import java.util.Map;
 
+/**
+ * A container object that holds an {@link Element} with a "distance" as 
determined by a vector index.
+ */
 public class TinkerIndexElement<T> {
     private final T element;
     private final float distance;
diff --git 
a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphServiceTest.java
 
b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphServiceTest.java
index 2901ef76da..b7ba27d88e 100644
--- 
a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphServiceTest.java
+++ 
b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphServiceTest.java
@@ -25,10 +25,12 @@ import 
org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
 import 
org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
 import 
org.apache.tinkerpop.gremlin.process.traversal.traverser.util.TraverserSet;
 import org.apache.tinkerpop.gremlin.structure.Direction;
+import org.apache.tinkerpop.gremlin.structure.Edge;
 import org.apache.tinkerpop.gremlin.structure.Vertex;
 import 
org.apache.tinkerpop.gremlin.tinkergraph.services.TinkerDegreeCentralityFactory;
 import org.apache.tinkerpop.gremlin.tinkergraph.services.TinkerServiceRegistry;
 import 
org.apache.tinkerpop.gremlin.tinkergraph.services.TinkerTextSearchFactory;
+import 
org.apache.tinkerpop.gremlin.tinkergraph.services.TinkerVectorSearchFactory;
 import org.apache.tinkerpop.gremlin.util.function.TriFunction;
 import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
 import org.apache.tinkerpop.shaded.jackson.databind.ObjectMapper;
@@ -38,6 +40,7 @@ import org.junit.Test;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Comparator;
+import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
@@ -69,8 +72,12 @@ public class TinkerGraphServiceTest {
     final TinkerGraph graph = TinkerFactory.createModern();
     final GraphTraversalSource g = graph.traversal();
 
+    static final Map<String,Object> indexConfig = new HashMap<String,Object>() 
{{
+        put(TinkerVectorIndex.CONFIG_DIMENSION, 3);
+    }};
+
     @Before
-    public void registerServices() {
+    public void setup() {
         graph.getServiceRegistry().registerService(new 
TinkerTextSearchFactory(graph));
         graph.getServiceRegistry().registerService(new 
TinkerDegreeCentralityFactory(graph));
     }
@@ -81,31 +88,31 @@ public class TinkerGraphServiceTest {
     @Test
     public void g_call() throws Exception {
         /*
-         * Tinkergraph has one registered service by default ("tinker.search").
+         * TinkerGraph has one registered service by default ("tinker.search").
          */
         assertArrayEquals(new String[] {
-                "tinker.search",
-                "tinker.degree.centrality"
+                TinkerTextSearchFactory.NAME,
+                TinkerDegreeCentralityFactory.NAME,
                 }, toResultStrings(
 
                 g.call()
 
         ));
         assertArrayEquals(new String[] {
-                "tinker.search",
-                "tinker.degree.centrality"
+                TinkerTextSearchFactory.NAME,
+                TinkerDegreeCentralityFactory.NAME,
                 }, toResultStrings(
 
                 g.call("--list")
 
         ));
 
-        checkResult("tinker.search",
-                g.call("--list").with("service", "tinker.search"));
+        checkResult(TinkerTextSearchFactory.NAME,
+                g.call("--list").with("service", 
TinkerTextSearchFactory.NAME));
 
-        
checkResult("{\"name\":\"tinker.search\",\"type:[requirements]:\":{\"Start\":[]},"
 +
+        checkResult("{\"name\":\"" + TinkerTextSearchFactory.NAME + 
"\",\"type:[requirements]:\":{\"Start\":[]}," +
                       "\"params\":"+new 
ObjectMapper().writeValueAsString(TinkerTextSearchFactory.Params.DESCRIBE)+"}",
-                g.call("--list").with("service", 
"tinker.search").with("verbose"));
+                g.call("--list").with("service", 
TinkerTextSearchFactory.NAME).with("verbose"));
     }
 
     /**
@@ -118,7 +125,7 @@ public class TinkerGraphServiceTest {
          */
         assertEquals("[path[vp[name->marko], v[1]]]", toResultString(
 
-            g.call("tinker.search", asMap("search", "mar"))
+            g.call(TinkerTextSearchFactory.NAME, asMap("search", "mar"))
                 .element().path()
 
         ));
@@ -128,7 +135,7 @@ public class TinkerGraphServiceTest {
          */
         assertEquals("[path[vp[name->vadas], v[2]]]", toResultString(
 
-            g.call("tinker.search", (Traversal) 
__.project("search").by(V(2).values("name")))
+            g.call(TinkerTextSearchFactory.NAME, (Traversal) 
__.project("search").by(V(2).values("name")))
                 .element().path()
 
         ));
@@ -143,7 +150,7 @@ public class TinkerGraphServiceTest {
                 "path[p[weight->0.2], e[12][6-created->3]]"
                 }, toResultStrings(
 
-            g.call("tinker.search").with("search", __.constant("2"))
+            g.call(TinkerTextSearchFactory.NAME).with("search", 
__.constant("2"))
                 .element().path()
 
         ));
@@ -157,7 +164,7 @@ public class TinkerGraphServiceTest {
                 "path[vp[age->32], v[4]]",
         }, toResultStrings(
 
-                g.call("tinker.search").with("search", 
__.constant("2")).with("type", "Vertex")
+                g.call(TinkerTextSearchFactory.NAME).with("search", 
__.constant("2")).with("type", "Vertex")
                         .element().path()
 
         ));
@@ -175,7 +182,7 @@ public class TinkerGraphServiceTest {
                 "{vertex=v[6], degree=0}",
         }, toResultStrings(
 
-                g.V().as("v").call("tinker.degree.centrality")
+                g.V().as("v").call(TinkerDegreeCentralityFactory.NAME)
                         .project("vertex", "degree").by(select("v")).by()
 
         ));
@@ -189,14 +196,14 @@ public class TinkerGraphServiceTest {
                 "{vertex=peter, degree=1}",
         }, toResultStrings(
 
-                
g.V().as("v").call("tinker.degree.centrality").with("direction", Direction.OUT)
+                
g.V().as("v").call(TinkerDegreeCentralityFactory.NAME).with("direction", 
Direction.OUT)
                         .project("vertex", 
"degree").by(select("v").values("name")).by()
 
         ));
 
-        checkResult("lop", 
g.V().where(__.call("tinker.degree.centrality").is(3)).values("name"));
-        checkResults(Arrays.asList("vadas","josh","ripple"), 
g.V().where(__.call("tinker.degree.centrality").is(1)).values("name"));
-        checkResult(0l, 
g.V().where(__.call("tinker.degree.centrality").is(100)).count());
+        checkResult("lop", 
g.V().where(__.call(TinkerDegreeCentralityFactory.NAME).is(3)).values("name"));
+        checkResults(Arrays.asList("vadas","josh","ripple"), 
g.V().where(__.call(TinkerDegreeCentralityFactory.NAME).is(1)).values("name"));
+        checkResult(0l, 
g.V().where(__.call(TinkerDegreeCentralityFactory.NAME).is(100)).count());
     }
 
     /**
@@ -445,6 +452,145 @@ public class TinkerGraphServiceTest {
         checkResults(Arrays.asList(4, 2), g.V().call(serviceName, 
asMap(LambdaServiceFactory.Options.TYPE, Type.Barrier, 
LambdaServiceFactory.Options.CHUNK_SIZE, 4)));
     }
 
+    @Test
+    public void g_V_callXvector_topKByVertex_key_embeddingX() {
+        final TinkerGraph graf = TinkerGraph.open();
+        graf.getServiceRegistry().registerService(new 
TinkerVectorSearchFactory(graf));
+        graf.createIndex(TinkerIndexType.VECTOR, "embedding", Vertex.class, 
indexConfig);
+        final GraphTraversalSource gv = graf.traversal();
+
+        final Vertex vAlice = gv.addV("person").property("name", 
"Alice").property("embedding", new float[]{1.0f, 0.0f, 0.0f}).next();
+        final Vertex vBob = gv.addV("person").property("name", 
"Bob").property("embedding", new float[]{0.05f, 1.0f, 0.0f}).next();
+        final Vertex vCharlie = gv.addV("person").property("name", 
"Charlie").property("embedding", new float[]{0.0f, 0.0f, 1.0f}).next();
+        final Vertex vDave = gv.addV("person").property("name", 
"Dave").property("embedding", new float[]{0.9f, 0.1f, 0.0f}).next();
+
+        final Map<String,Object> m = new HashMap<String,Object>() {{
+            put("key", "embedding");
+        }};
+        final List<Object> list = 
gv.V(vAlice).call(TinkerVectorSearchFactory.NAME, m).toList();
+
+        final List<Map<String,Object>> expected = new ArrayList<>();
+        expected.add(asMap("distance", 0.006116271f, "element", vDave));
+        expected.add(asMap("distance", 0.9500624f, "element", vBob));
+        expected.add(asMap("distance", 1.0f, "element", vCharlie));
+
+        // Use a custom comparison to ensure the lists are equal
+        assertEquals(expected.size(), list.size());
+        for (int i = 0; i < expected.size(); i++) {
+            assertEquals(expected.get(i).get("distance"), ((Map) 
list.get(i)).get("distance"));
+            assertEquals(expected.get(i).get("element"), ((Map) 
list.get(i)).get("element"));
+        }
+    }
+
+    @Test
+    public void g_E_callXvector_topKByEdge_key_embeddingX() {
+        final TinkerGraph graf = TinkerGraph.open();
+        graf.getServiceRegistry().registerService(new 
TinkerVectorSearchFactory(graf));
+        graf.createIndex(TinkerIndexType.VECTOR, "embedding", Edge.class, 
indexConfig);
+        final GraphTraversalSource gv = graf.traversal();
+
+        final Vertex vAlice = gv.addV("person").property("name", 
"Alice").next();
+        final Vertex vBob = gv.addV("person").property("name", "Bob").next();
+        final Vertex vCharlie = gv.addV("person").property("name", 
"Charlie").next();
+
+        final Edge e1 = 
gv.addE("knows").from(vAlice).to(vBob).property("embedding", new float[]{1.0f, 
0.0f, 0.0f}).next();
+        final Edge e2 = 
gv.addE("knows").from(vAlice).to(vCharlie).property("embedding", new 
float[]{0.0f, 1.0f, 0.0f}).next();
+        final Edge e3 = 
gv.addE("knows").from(vBob).to(vCharlie).property("embedding", new 
float[]{0.5f, 0.5f, 0.0f}).next();
+
+        final Map<String, Object> m = new HashMap<String, Object>() {{
+            put("key", "embedding");
+        }};
+        final List<Object> list = 
gv.E(e1).call(TinkerVectorSearchFactory.NAME, m).toList();
+
+        final List<Map<String, Object>> expected = new ArrayList<>();
+        expected.add(asMap("distance", 0.29289323f, "element", e3));
+        expected.add(asMap("distance", 1.0f, "element", e2));
+
+        // Use a custom comparison to ensure the lists are equal
+        assertEquals(expected.size(), list.size());
+        for (int i = 0; i < expected.size(); i++) {
+            assertEquals(expected.get(i).get("distance"), ((Map) 
list.get(i)).get("distance"));
+            assertEquals(expected.get(i).get("element"), ((Map) 
list.get(i)).get("element"));
+        }
+    }
+
+    @Test
+    public void g_V_callXvector_topKByVertex_key_embedding_topK_1X() {
+        final TinkerGraph graf = TinkerGraph.open();
+        graf.getServiceRegistry().registerService(new 
TinkerVectorSearchFactory(graf));
+        graf.createIndex(TinkerIndexType.VECTOR, "embedding", Vertex.class, 
indexConfig);
+        final GraphTraversalSource gv = graf.traversal();
+
+        final Vertex vAlice = gv.addV("person").property("name", 
"Alice").property("embedding", new float[]{1.0f, 0.0f, 0.0f}).next();
+        final Vertex vBob = gv.addV("person").property("name", 
"Bob").property("embedding", new float[]{0.05f, 1.0f, 0.0f}).next();
+        final Vertex vCharlie = gv.addV("person").property("name", 
"Charlie").property("embedding", new float[]{0.0f, 0.0f, 1.0f}).next();
+        final Vertex vDave = gv.addV("person").property("name", 
"Dave").property("embedding", new float[]{0.9f, 0.1f, 0.0f}).next();
+
+        final Map<String,Object> m = new HashMap<String,Object>() {{
+            put("key", "embedding");
+            put("topK", 1);
+        }};
+        final List<Object> list = 
gv.V(vAlice).call(TinkerVectorSearchFactory.NAME, m).toList();
+
+        final List<Map<String,Object>> expected = new ArrayList<>();
+        expected.add(asMap("distance", 0.006116271f, "element", vDave));
+
+        // Use a custom comparison to ensure the lists are equal
+        assertEquals(expected.size(), list.size());
+        for (int i = 0; i < expected.size(); i++) {
+            assertEquals(expected.get(i).get("distance"), ((Map) 
list.get(i)).get("distance"));
+            assertEquals(expected.get(i).get("element"), ((Map) 
list.get(i)).get("element"));
+        }
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void g_V_callXvector_missing_keyX() {
+        final TinkerGraph graf = TinkerGraph.open();
+        graf.getServiceRegistry().registerService(new 
TinkerVectorSearchFactory(graf));
+        graf.createIndex(TinkerIndexType.VECTOR, "embedding", Vertex.class, 
indexConfig);
+        final GraphTraversalSource gv = graf.traversal();
+
+        final Vertex vAlice = gv.addV("person").property("name", 
"Alice").property("embedding", new float[]{1.0f, 0.0f, 0.0f}).next();
+
+        // Missing key parameter should cause a IllegalArgumentException when 
trying to access it
+        final Map<String,Object> emptyParams = new HashMap<>();
+        gv.V(vAlice).call(TinkerVectorSearchFactory.NAME, 
emptyParams).toList();
+    }
+
+    @Test
+    public void g_V_callXvector_nonexistent_propertyX() {
+        final TinkerGraph graf = TinkerGraph.open();
+        graf.getServiceRegistry().registerService(new 
TinkerVectorSearchFactory(graf));
+        graf.createIndex(TinkerIndexType.VECTOR, "embedding", Vertex.class, 
indexConfig);
+        final GraphTraversalSource gv = graf.traversal();
+
+        final Vertex vAlice = gv.addV("person").property("name", 
"Alice").next(); // No embedding property
+
+        // Referencing a non-existent property should return no results
+        final Map<String,Object> params = new HashMap<String,Object>() {{
+            put("key", "embedding");
+        }};
+
+        assertEquals(0, gv.V(vAlice).call(TinkerVectorSearchFactory.NAME, 
params).count().next().intValue());
+    }
+
+    @Test
+    public void g_V_properties_callXvector_nonexistent_propertyX() {
+        final TinkerGraph graf = TinkerGraph.open();
+        graf.getServiceRegistry().registerService(new 
TinkerVectorSearchFactory(graf));
+        graf.createIndex(TinkerIndexType.VECTOR, "embedding", Vertex.class, 
indexConfig);
+        final GraphTraversalSource gv = graf.traversal();
+
+        final Vertex vAlice = gv.addV("person").property("name", 
"Alice").property("embedding", new float[]{1.0f, 0.0f, 0.0f}).next();
+
+        final Map<String,Object> params = new HashMap<String,Object>() {{
+            put("key", "embedding");
+        }};
+
+        // Referencing things other than vertex or edge should return no 
results
+        assertEquals(0, 
gv.V(vAlice).properties().call(TinkerVectorSearchFactory.NAME, 
params).count().next().intValue());
+    }
+
     private String toResultString(final Traversal traversal) {
         return (String) 
IteratorUtils.stream(traversal).map(Object::toString).collect(Collectors.joining(",",
 "[", "]"));
     }

Reply via email to