Как Gremlin запрашивает тот же sql, что и функция поиска

Я использую график типа OrientDB. Мне нужен синтаксис Gremlin для поиска того же оператора SQL LIKE

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

Я проверил с помощью has и filter (в http://gremlindocs.com/). Однако он должен определить, что точное значение передается с типом свойства. Я думаю, что это неправильно с логикой поиска.

Спасибо за что угодно.


person Minh Loc    schedule 30.09.2013    source источник


Ответы (7)


Пытаться:

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

or

g.V().filter({ it.getProperty("foo").contains("search") })
person Daniel Kuppitz    schedule 30.09.2013
comment
и .matches(".*search.*") - person Minh Loc; 01.10.2013
comment
есть ли способ сделать "не нравится"? - person Govind Prabhu; 27.07.2017
comment
Просто верните инвертированный результат. g.V().filter({ !it.getProperty("foo").contains("search") }) - person Daniel Kuppitz; 27.07.2017
comment
Какой сервер Gremlin вы используете для этого? Титан? Янус? - person Luis Bosquez; 06.06.2018
comment
Во-первых, этому ответу 5 лет, Януса в то время не существовало. Далее, я не думаю, что использовал какой-либо сервер для проверки этого запроса. - person Daniel Kuppitz; 28.06.2018

Для поддержки Cosmos Db Gremlin

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

Вы можете найти документацию документы службы поддержки Microsoft Gremlin и Справочник по TinkerPop

person Chris Stubbs    schedule 03.03.2020

Вы можете использовать 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 на сервер или используете запросы на основе байт-кода. Если вы отправляете скрипты, вы сможете отправить запрос, как показано выше. Если вы используете байт-код, вы должны явно объявить лямбду как строку в вашем обходе, как показано здесь для Python.

В конечном счете, использование замыканий/лямбда-выражений не рекомендуется, поскольку они снижают переносимость вашего кода, обнажают дыры в безопасности и т. д. Если вам нужны регулярные выражения, лучше всего использовать граф, который имеет встроенную поддержку для них, и библиотеку кода, содержащую настраиваемые предикаты, специфичные для вашего языка программирования.

person stephen mallette    schedule 30.09.2013
comment
Как я могу использовать регулярное выражение (совпадения) с javascript Gremlin, пожалуйста? - person Đỗ Công Bằng; 09.07.2018
comment
@CongBangDO - Вы когда-нибудь узнавали как? - person L G; 04.04.2019
comment
я обновил этот ответ для TinkerPop 3.x - обратите внимание, что gremlin-javascript еще не поддерживает закрытие/лямбды для обходов на основе байт-кода. вы должны были бы отправить сценарий. не отличное решение, но это все, что есть. - person stephen mallette; 04.04.2019
comment
Большое спасибо за обновление @stephenmallette - я очень новичок во всем этом. Могу я спросить, что плохого в отправке скриптов? - person L G; 04.04.2019
comment
TinkerPop обычно рекомендует байт-код как предпочтительный способ работы. Вспомните, как некрасиво встраивать строки SQL в свой код — не так уж и отличается Gremlin. вы не получаете поддержки IDE, такой как автозаполнение, не знаете об ошибках времени компиляции и т. д. Скрипты также являются дырой в безопасности, если они не настроены должным образом, поскольку они могут позволить выполнение произвольного кода. Сценарии также обязывают вас писать Gremlin на языке, отличном от того, который вы, возможно, используете — если вы кодируете JS, вам придется писать Gremlin как Groovy, если вы отправляете сценарии. - person stephen mallette; 04.04.2019
comment
Имеет смысл; и да, это своего рода шаг назад к темным векам со строками БД в коде. Я просто должен попробовать и использовать его только в случае крайней необходимости. Последний вопрос (на данный момент :)) — я вижу, вы активно вносите свой вклад в код tinkerpop (спасибо) — являются ли замыкания/лямбды частью дорожной карты для gremlin-javascript? - person L G; 04.04.2019
comment
да - это просто то, что еще не было сделано (однако поддержка среди поставщиков графиков может быть неравномерной - не все поддерживают лямбда-выражения по той же причине, что и скрипты): issues.apache.org/jira/browse/TINKERPOP-2001 - person stephen mallette; 04.04.2019
comment
@LG К сожалению, я этого не сделал. - person Đỗ Công Bằng; 07.04.2019

Для людей, которые найдут этот ответ, здесь есть обновленная версия того, как вы можете искать (очень похоже на принятый ответ)

Для консоли гремлина (gremlin.sh):

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

Кроме того, если у вас есть серверная часть индекса ElasticSearch (может работать и для других серверных частей индексации), это также работает:

g.V().has("foo", Text.textContains("search"))
person Andreas Klintberg    schedule 26.08.2019

Для JanusGraph с Gremlin Python (gremlin_python):

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

Источник: https://docs.janusgraph.org/index-backend/text-search/

person Thiago Falcao    schedule 08.05.2020

Как один из коммиттеров проекта 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);
    }
}
person Wolfgang Fahl    schedule 13.05.2018

Я знаю, что опоздал с этим, но я тоже пытался понять это и надеюсь, что это кому-то поможет. Это реализовано на Java. ТинкерПоп версии 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
person Sam B    schedule 12.08.2017