【问题标题】:How Gremlin query same sql like for search featureGremlin 如何像搜索功能一样查询相同的 sql
【发布时间】:2013-10-05 18:38:26
【问题描述】:

我正在使用 OrientDB 类型的图。我需要 Gremlin 的语法来搜索相同的 SQL LIKE 运算符

LIKE 'search%' or LIKE '%search%'

我已经检查了 has 和 filter(在 http://gremlindocs.com/ 中)。但是,它必须确定使用 type 属性传递的确切值。我认为这不符合搜索逻辑。

谢谢你。

【问题讨论】:

    标签: sql gremlin orientdb


    【解决方案1】:

    对于 Cosmos Db Gremlin 支持

    g.V().has('foo', TextP.containing('search'))
    

    你可以找到文档Microsoft Gremlin Support docsTinkerPop Reference

    【讨论】:

      【解决方案2】:

      试试:

      g.V().filter({ it.getProperty("foo").startsWith("search") })
      

      g.V().filter({ it.getProperty("foo").contains("search") })
      

      【讨论】:

      • .matches(".*search.*")
      • 有什么办法可以“不喜欢”吗?
      • 只返回反转结果。 g.V().filter({ !it.getProperty("foo").contains("search") })
      • 您为此使用什么 Gremlin 服务器?泰坦?杰纳斯?
      • 首先,这个答案已有 5 年历史,此时 Janus 不存在。接下来,我想我没有使用任何服务器来测试这个查询。
      【解决方案3】:

      您可以使用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 表示法,它引用V() 流中的当前Traverser,它包含一个通过get() 检索的Vertex 对象。

      这种方法适用于任何接受闭包的地方,但它们并不适用于任何地方,因为并非所有图表都支持它们。如果您不在 JVM(例如 python)上,那么您可能会将 Gremlin 脚本提交到服务器或使用基于字节码的请求。如果您正在提交脚本,那么您应该能够如上所示提交请求。如果您使用字节码,则必须在遍历中将 lambda 显式声明为字符串,如 Python 中的 here 所示。

      最终,不建议使用闭包/lambda,因为它们会降低代码的可移植性,暴露安全漏洞等。如果您需要正则表达式,最好使用对它们具有本机支持的图形和代码库包含特定于您的编程语言的自定义谓词。

      【讨论】:

      • 请问如何将正则表达式(匹配项)与 gremlin javascript 一起使用?
      • @CongBangDO - 你知道怎么做吗?
      • 我已经为 TinkerPop 3.x 更新了这个答案 - 请注意,gremlin-javascript 还不支持基于字节码的遍历的闭包/lambdas。你将不得不发送一个脚本。不是一个很好的解决方案,但就是这样。
      • 非常感谢@stephenmallette 的更新——我对这一切都很陌生。请问发送脚本有什么“不好”的地方?
      • TinkerPop 通常推荐字节码作为首选的做事方式。回想一下在代码中嵌入 SQL 字符串是多么难看——对于 Gremlin 来说并没有太大的不同。您没有像自动完成这样的 IDE 支持,不知道编译时错误等。如果配置不正确,脚本也是一个安全漏洞,因为它们可以启用任意代码执行。脚本还会让您使用不同于您可能使用的语言编写 Gremlin - 如果您编写 JS 代码,那么如果您提交脚本,则必须将 Gremlin 编写为 Groovy。
      【解决方案4】:

      对于在此处找到此答案的人来说,这是您如何搜索的更新版本(与接受的答案非常相似)

      对于 gremlin 控制台 (gremlin.sh):

      g.V().filter({ it.get().value("foo").contains("search") })
      

      此外,如果您的索引后端是 ElasticSearch(可能也适用于其他索引后端),这也可以:

      g.V().has("foo", Text.textContains("search"))
      

      【讨论】:

        【解决方案5】:

        对于带有 Gremlin Python (gremlin_python) 的 JanusGraph:

        from gremlin_python.process.traversal import TextP
        g.V().has('foo', TextP.containing('search'))
        

        来源:https://docs.janusgraph.org/index-backend/text-search/

        【讨论】:

          【解决方案6】:

          作为 SimpleGraph 项目的提交者之一,我知道该项目中实施的解决方案

          https://github.com/BITPlan/com.bitplan.simplegraph/blob/master/simplegraph-core/src/main/java/com/bitplan/gremlin/RegexPredicate.java

          示例

          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);
              }
          }
          

          【讨论】:

            【解决方案7】:

            我知道我在这方面已经很晚了,但我也在努力解决这个问题,并希望它对那里的人有所帮助。这是用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
            

            【讨论】:

              猜你喜欢
              • 2018-10-17
              • 1970-01-01
              • 1970-01-01
              • 2015-10-25
              • 1970-01-01
              • 2012-03-09
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多