COLLECT() заставляет функцию входить в бесконечный цикл загрузки

#neo4j #cypher #collect

Вопрос:

В Neo4j у меня есть набор графиков, состоящий из начальных терминов и синонимов, добавляемых к этим начальным терминам через отношения [:SYNONYM_OF] . Я пишу функцию, в которой любой узел, содержащий слово, соответствующее синониму определенного начального термина, возвращается вместе с любыми соответствующими перечисленными синонимами. Мой текущий запрос показан ниже:

 MATCH (b)-[*]->(z)-[*]->(n),
      (syn)<-[r]->(seed:Seed_Term {name: "valuation"})
WHERE (
  (
    n.name CONTAINS toLower(syn.name)
    OR n.content CONTAINS toLower(syn.name)
  )
  OR (
    n.name CONTAINS toUpper(syn.name)
    OR n.content CONTAINS toUpper(syn.name)
  )
)
AND (b:Label)
AND (n:Title OR n:Text OR n:Column OR n:RowName OR n:Cell)
AND (z:Pdf)
RETURN n.name AS node,
       syn.name AS synonym_found,
       seed.name AS seed_term,
       b.labelName AS company,
       z.year AS year,
       r AS rel_type
LIMIT 1000
 

Единственная проблема с этим заключается в том, что если найдено три разных синонима, он возвращает строку, содержащую содержимое (узел) три раза, причем синоним_поиск каждый раз отличается. Я знаю , что вместо этого я должен делать collect(syn.name) , а не syn.name , однако всякий раз, когда я это делаю, код входит в бесконечный цикл до такой степени, что мне просто нужно завершить запрос. Это происходит, даже если я пишу LIMIT 1 в конце. Почему это collect() происходит?

Ответ №1:

Ваш MATCH — декартово произведение в сочетании с (неопределенными) путями переменной длины. Это очень интенсивный запрос.

Я бы разделил запрос на (1) сопоставление синонимов, а затем (2) получение дополнительной информации об узле:

 MATCH (seed:Seed_Term {name: "valuation"})-[r]-(syn), (n)
WHERE (n:Title OR n:Text OR n:Column OR n:RowName OR n:Cell)
AND (
  n.name =~ "(?i).*"   syn.name   ".*" // case insensitive regular expression
  OR n.content =~ "(?i).*"   syn.name   ".*"
)
WITH seed, n, r, collect(syn.name) AS synonyms
MATCH (n)<-[*]-(z:Pdf)<-[*]-(b:Label)
RETURN n.name AS node,
       synonyms,
       seed.name AS seed_term,
       b.labelName AS company,
       z.year AS year,
       type(r) AS rel_type
LIMIT 1000
 

Я не проверял этот запрос, но, возможно, он приведет вас в правильном направлении.