Dgraph глубокая фильтрация - PullRequest
0 голосов
/ 16 марта 2019

У меня есть схема

<friend>: uid .
<owns_pet>: uid .
<person.age>: int @index(int) .
<person.name>: string @index(fulltext, term, trigram) .
<pet.name>: string @index(fulltext, term) .

с данными

{
  set {
    _:a1 <person.name> "A1" .
    _:a1 <person.age> "43" .
    _:a2 <person.name> "A2" .
    _:a2 <person.age> "33" .
    _:a3 <person.name> "A3" .
    _:a3 <person.age> "37" .
    _:a1 <friend> _:a2 .
    _:a1 <friend> _:a3 .
    _:a3 <friend> _:a2 .
    _:p2 <pet.name> "P2" .
    _:p3 <pet.name> "P3" .
    _:a2 <owns_pet> _:p2 .
    _:a3 <owns_pet> _:p3 .
  }
}

Можно ли создать запрос, который возвращает только лиц, у которых есть друг, и у этого друга есть домашнее животное с именем "P3"? Я ожидаю увидеть в результате

"result": [
  {
    "name": "A1",
    "age": 43
  }
]

На данный момент я смог запросить:

{
  result (func: has(person.name)) @filter(has(friend)) {
    name: person.name
    age: person.age
    friend @filter(has(owns_pet)) {
      owns_pet @filter(eq(pet.name, "P3")) {
      }
    }
  }
}

но это также возвращает человека "A3"

Ответы [ 2 ]

1 голос
/ 04 апреля 2019

Вот еще один запрос, который вы могли бы рассмотреть, используя @normalize, чтобы возвращать только псевдонимы, а @cascade, чтобы возвращать только результаты, содержащие все ребра в запросе:

{
  personWithFriendPetP3(func: has(person.name)) @normalize @cascade {
    name: person.name
    age: person.age
    friend {
      owns_pet @filter(eq(pet.name, "P3")) {
        pet.name
      }
    }
  }
}

Ответ:

{
  "data": {
    "personWithFriendPetP3": [
      {
        "name": "A1",
        "age": 43
      }
    ]
  }
}

Ваш ответ будет отлично работать, если вы установите обратные ребра в типах схем для owns_pet и friend.Он будет выполнять меньше работы, чем приведенный выше запрос, поскольку он использует индексированный запрос в корневой функции с проверкой равенства сначала для определенного имени питомца, а затем переходит для других друзей.

Запрос в этомВ ответе сначала будут найдены все люди с именами в корневой функции, а затем проверено, является ли имя питомца их друга P3.


Dgraph docs:

https://docs.dgraph.io/query-language/#normalize-directive

https://docs.dgraph.io/query-language/#cascade-directive

1 голос
/ 17 марта 2019

Нашел одно решение, которое возвращает необходимые результаты:

{
  var (func: eq(pet.name, "P3")) {
    ~owns_pet {
      ~friend {
        u as uid
      }
    }  
  }

  result (func: uid(u)) {
    name: person.name
    age: person.age
  }
}

, но я не знаю, правильный ли это путь.

...