我使用 OrientDB 类型图。我需要 Gremlin 的语法来搜索相同的 SQL LIKE 运算符
LIKE 'search%' or LIKE '%search%'
我已经检查了 has 和 filter(在http://gremlindocs.com/中)。但是,它必须确定使用 type 属性传递的确切值。我认为这与搜索逻辑不正确。
感谢一切。
我使用 OrientDB 类型图。我需要 Gremlin 的语法来搜索相同的 SQL LIKE 运算符
LIKE 'search%' or LIKE '%search%'
我已经检查了 has 和 filter(在http://gremlindocs.com/中)。但是,它必须确定使用 type 属性传递的确切值。我认为这与搜索逻辑不正确。
感谢一切。
对于 Cosmos Db Gremlin 支持
g.V().has('foo', TextP.containing('search'))
尝试:
g.V().filter({ it.getProperty("foo").startsWith("search") })
或者
g.V().filter({ it.getProperty("foo").contains("search") })
您可以使用filter
一些正则表达式:
gremlin> g = TinkerGraphFactory.createTinkerGraph()
==>tinkergraph[vertices:6 edges:6]
gremlin> g.V.filter{it.name.matches(".*ark.*")}.name
==>marko
或者使用更多 Groovy 语法糖:
gremlin> g.V.filter{it.name==~/.*ark.*/}.name
==>marko
上述答案(和接受的答案)适用于 TinkerPop 2.x,以下适用于 3.x,这是目前广泛使用的版本:
目前,TinkerPop 3.x 不支持将正则表达式作为 Gremlin 核心语言的一部分,但是正则表达式可能适用于您正在使用的特定图形系统(DSE Graph、JanusGraph 等),并且这些图形将提供自己的库来扩展带有正则表达式谓词(和/或其他搜索选项,如模糊和标记化)的 Gremlin。请查阅图表的文档以了解可用的内容。
特定于图形的扩展将是进行基于正则表达式的搜索的最有效方法,因为它将依赖于为处理此类事情而优化的内部索引函数,但是有一些方法可以通过类似的闭包进行内存中的正则表达式搜索到上面的 TinkerPop 2.x 答案。
gremlin> g = TinkerFactory.createModern().traversal()
==>graphtraversalsource[tinkergraph[vertices:6 edges:6], standard]
gremlin> g.V().filter{it.get().value('name').matches(".*ark.*")}
==>v[1]
由于我们使用的是闭包,因此我们可以在该函数中放置我们想要的任何 Java(在本例中为 Groovy)代码。请注意,forit.get().value('name')
是it
一个 Groovy 表示法,它引用流中的当前Traverser
流,V()
并且它包含一个Vertex
通过 检索的对象get()
。
这种方法适用于任何接受闭包的地方,但它们并不适用于任何地方,因为并非所有图表都支持它们。如果您不在 JVM(例如 python)上,那么您可能会将 Gremlin 脚本提交到服务器或使用基于字节码的请求。如果您正在提交脚本,那么您应该能够如上所示提交请求。如果您使用的是字节码,那么您必须在遍历中将 lambda 显式声明为字符串,如此处针对 Python 所示。
最终,不建议使用闭包/lambda,因为它们会降低代码的可移植性,暴露安全漏洞等。如果您需要正则表达式,最好使用对它们具有本机支持的图形和包含特定于您的编程语言的自定义谓词。
对于在此处找到此答案的人来说,这是您如何搜索的更新版本(与接受的答案非常相似)
对于 gremlin 控制台 (gremlin.sh):
g.V().filter({ it.get().value("foo").contains("search") })
此外,如果您的索引后端是 ElasticSearch(可能也适用于其他索引后端),这也可以:
g.V().has("foo", Text.textContains("search"))
对于带有 Gremlin Python (gremlin_python) 的 JanusGraph:
from gremlin_python.process.traversal import TextP
g.V().has('foo', TextP.containing('search'))
作为 SimpleGraph 项目的提交者之一,我知道该项目中实施的解决方案
例子
g().V().has("tosearch", RegexPredicate.regex("search.*"))
正则表达式谓词
import java.util.function.BiPredicate;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.tinkerpop.gremlin.process.traversal.P;
// https://groups.google.com/forum/#!topic/gremlin-users/heWLwz9xBQc
// https://stackoverflow.com/a/45652897/1497139
public class RegexPredicate implements BiPredicate<Object, Object> {
Pattern pattern = null;
private Mode mode;
enum Mode {
FIND, MATCH
}
public RegexPredicate(String regex, Mode mode) {
this.mode = mode;
pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
};
public RegexPredicate(String regex) {
this(regex,Mode.FIND);
}
@Override
public boolean test(final Object first, final Object second) {
String str = first.toString();
Matcher matcher = pattern.matcher(str);
switch (mode) {
case FIND:
return matcher.find();
case MATCH:
return matcher.matches();
}
return false;
}
/**
* get a Regular expression predicate
*
* @param regex
* @return - the predicate
*/
public static P<Object> regex(Object regex) {
BiPredicate<Object, Object> b = new RegexPredicate(regex.toString());
return new P<Object>(b, regex);
}
}
我知道我在这方面已经很晚了,但我也试图弄清楚这一点,并希望它对那里的人有所帮助。这是用Java实现的。TinkerPop 版本 3.2.5。如果不编写一些 Java,我不知道如何做到这一点。
1) 创建一个实现 BiPredicate 的枚举。(注意,这个谓词允许使用通配符并且不区分大小写。)
public enum StringCompare implements BiPredicate<Object, Object> {
wildcard {
@Override
public boolean test(final Object first, final Object second) {
String str = first.toString();
String regex = second.toString();
Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(str);
return matcher.matches();
}
}
}
2) 按照 Java 规则创建正则表达式。我发现这个链接很有帮助。http://www.developer.com/java/data/using-java-regular-expressions.html
3) 使用 has() 方法,将属性键传递给它,并创建一个新的 P 对象。
String regex = "Mar.*"; //2
GraphTraversal<Vertex,Vertex> gtv = g.V().has("name", new P<>(StringCompare.wildcard, regex)); //3