Как написать запрос гремлина, который находит общие вершины между другими вершинами и возвращает отсортированные по количеству перекрытий?

Я использую python + gremlin для реализации своих запросов к графу, но все еще далек от понимания многих концепций и столкнулся с интересным запросом, который не знаю, что делать.

Допустим, у нас есть несколько вершин шеф-повара с меткой Chef, вершин ингредиентов с меткой Ingredient и вершин блюд Dish. В любой момент времени у повара могут быть ингредиенты для использования, обозначенные границей между Chef и Ingredient и называются has. В блюдах есть ингредиенты, обозначенные краем между Dish и Ingredient и называемые uses. Также есть граница между Chef и Dish, указывающая, делал ли он это раньше, называется madeBefore.

Наверное, это очевидно, но есть Блюда, которые никогда не готовил шеф-повар, и не во всех Блюдах используются все ингредиенты, а у шеф-повара, скорее всего, нет всех ингредиентов.

Я хотел бы создать запрос, который выполняет следующие действия:

Получите блюда, которые никогда не готовил шеф-повар, отсортированные по блюдам, которые содержат наибольшее количество ингредиентов, которые должен приготовить шеф-повар (если можно получить соотношение, тоже было бы здорово). Итак, первые блюда в результатах - это те, которые шеф-повар никогда не готовил, и, возможно, у них есть все ингредиенты для приготовления, где-то в середине результатов оказываются блюда, которые они никогда не готовили, и в которых содержится около половины ингредиентов, необходимых для их приготовления, и последнее. были бы блюдами, которых они никогда не готовили, а также практически не имели бы ингредиентов, необходимых для их приготовления.

Следующий запрос найдет все блюда, которые никогда не готовил шеф-повар:

g.V()\
    .hasLabel("Dish")\
    .filter(
        __.not_(
            __.in_("madeBefore").has("Chef", "name", "chefbot1")
        ))\
    .valueMap(True)\
    .toList()

Но отсюда я просто не знаю, с чего начать, чтобы начать сортировку этих блюд в зависимости от того, сколько ингредиентов есть у шеф-повара.

Моей другой мыслью было вместо этого запросить ингредиенты и использовать project, чтобы получить количество ребер, соединяющих как шеф-повара, так и блюдо, а затем каким-то образом их отфильтровать, но я не знаю, что делать после:

g.V()\
    .hasLabel("Ingredient")\
    .filter(
        __.in_("has").has("Chef", "name", "chefbot1"))\
    .project("v", "dishesUsingIngredient")\
    .by(valueMap(True))\
    .by(inE().hasLabel("uses").count())\
    .order().by("dishesUsingIngredient", Order.desc)\
    .toList()

Моя проблема с Gremlin сейчас заключается в том, чтобы понять, как объединить более сложные запросы в цепочку, есть ли кто-нибудь, кто может пролить свет на то, как решить эту проблему?


person jupiar    schedule 12.05.2020    source источник


Ответы (1)


Если я понял ваше описание, вы можете сделать что-то вроде этого:

g.V().hasLabel('Dish').
  filter(__.not(__.in('madeBefore').
      has('Chef', 'name', 'chefbot1'))).
  group().by('name').
    by(out('uses').in('has').
      has('Chef', 'name', 'chefbot1').count())
  .order(local).by(values)

пример: https://gremlify.com/8w

person noam621    schedule 12.05.2020
comment
gremlify.com ... Это потрясающий веб-сайт, о существовании которого я даже не подозревал. Ваш ответ очень помог мне понять, как строить такие запросы. В конечном итоге я использовал ваш код во втором блоке by() в group().by().by() и использовал его в операторе .project("overlapCount", "totalIngredientsCount").by().by() вместе с запросом общего количества ингредиентов, используемых в этом блюде, который я мог затем .order().by() и .range() для разбивки на страницы полученного списка. , которую я затем могу использовать простую функцию, чтобы вернуть соотношение после получения результатов - person jupiar; 13.05.2020