我使用OrientDB类型图。我需要Gremlin的语法来搜索相同的SQL LIKE运算符
LIKE 'search%' or LIKE '%search%'
我已检查过has和filter(在http://gremlindocs.com/中)。但是必须确定使用type属性传递的确切值。我认为这与搜索逻辑不一致。
谢谢你的一切。
尝试:
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)代码。请注意,对于it.get().value('name')
,it
是一个Groovy符号,它指的是Traverser
流中的当前V()
,它包含一个Vertex
对象,通过get()
检索。
这种方法适用于接受闭包的任何地方,但它们无法在任何地方使用,因为并非所有图形都支持它们。如果您不在JVM(例如python)上,那么您可能会将Gremlin脚本提交给服务器或使用基于字节码的请求。如果您要提交脚本,那么您应该能够提交请求,如上所示。如果您正在使用字节码,则必须在遍历中将lambda显式声明为字符串,如图所示here for Python。
最终,建议不要使用闭包/ lambda,因为它们会降低代码的可移植性,暴露安全漏洞等。如果你需要正则表达式,最好使用一个对它们有本机支持的图形和一个包含它的代码库。特定于您的编程语言的自定义谓词。
我知道我在这方面已经很晚了,但我也想弄清楚这一点,并希望它可以帮助那些人。这是用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
作为SimpleGraph项目的提交者之一,我知道该项目中实施的解决方案
例
g().V().has("tosearch", RegexPredicate.regex("search.*"))
RegexPredicate
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);
}
}