CQL — Как установить свойство Neo4j node, используя динамический ключ в cypher?

#neo4j #cypher #cql

#neo4j #cypher #cql

Вопрос:

Я пытаюсь исправить неправильные данные в моей базе данных Neo4j, и я хотел бы иметь просто cypher для обновления, а не передавать миллионы строк в пользовательское приложение и обратно.

Я создал запрос на чтение, который использует динамические ключи для поиска по каждому свойству на всех узлах меток, которые я указываю для различных типов проблем — в данном случае, неправильно сериализованной строки. Проблема, с которой я сталкиваюсь, заключается в том, что, хотя запрос на чтение с использованием динамических ключей работает отлично:

 MATCH (n:xLabelNamex) 
WITH 
    n, 
    [x IN keys(n) 
        WHERE n[x] STARTS WITH """ 
        AND n[x] ENDS WITH """
    ] AS doesMatch 
WHERE size(doesMatch) > 0 
UNWIND doesMatch AS label 
    MATCH (m:xLabelNamex) 
    WHERE id(n)=id(m)
    RETURN SUBSTRING(m[label], 1, SIZE(m[label]) - 2)
  

Но если я оставлю все то же самое и изменю последнюю строку с

 RETURN SUBSTRING(m[label], 1, SIZE(m[label]) - 2)
  

Для:

 SET m[label] = SUBSTRING(m[label], 1, length(m[label]) - 2)
  

Приводит к ошибке:

 Invalid input '[': expected an identifier character, node labels, a property map, whitespace, a relationship pattern, '(', '.', '=' or " =" (line 12, column 10 (offset: 255))
"    SET m[label] = SUBSTRING(m[label], 1, SIZE(m[label]) - 2)"
          ^
  

Есть ли способ сделать это, или я иду по неправильному пути здесь?

Просматривая обсуждения на Github, я вижу, что добавление чтения узлов с использованием динамических ключей было добавлено чуть больше года назад, но, похоже, они сделали это специально предназначенным только для чтения. Я начал копаться в исходниках Neo, но это чудовище. Буду признателен за любую помощь.

Комментарии:

1. AFAIK, вы правы, запись в свойства с динамическим ключом изначально не поддерживается в Cypher. Однако в apoc для этого есть много вариантов.

2. Apoc выглядит потрясающе, спасибо! Здесь есть тонна функций, есть какие-нибудь указания на то, с чего, по вашему мнению, мне следует начать поиск в документации для того, что я хочу сделать?

3. Я давно с этим не работал, но я полагаю, что вы можете создать карту с помощью apoc.map.fromPairs() , передать динамически сгенерированную пару ключ-значение, затем SET m = result где результат — это то, что вы называете результатом процедуры. Если ваш проект не мешает вам использовать бета-версии, я бы посоветовал переключиться на 3.1 и получить новейший APOC, он позволяет вам вызывать apoc.map как функцию вместо процедуры.

4. Этот проект требует передовых технологий во многих областях, поэтому бета-версии и тому подобное в значительной степени даны — я изучу 3.1. Спасибо за вашу помощь, высоко ценится!

Ответ №1:

Для всех, кто заходит после этого, библиотека Tore предложила — APOC — только что выпущенную версию 3.0.4.2, которая представила «apoc.create.setProperty» и делает именно то, что мне нужно. Кроме того, я обнаружил, что регулярные выражения в Neo4j выполняются НАМНОГО быстрее, чем поиск по прямому тексту (на порядок быстрее), поэтому я также воспользовался этим.

Мой окончательный шифр оказался:

 MATCH (n:xLabelNamex) 
WITH 
    n, 
    [x IN keys(n) 
        WHERE n[x] =~ '".*"'
    ] AS doesMatch 
WHERE size(doesMatch) > 0 
UNWIND doesMatch AS label 
    MATCH (m:xLabelNamex) 
    WHERE id(n)=id(m)
    CALL apoc.create.setProperty(m, label, SUBSTRING(m[label], 1, SIZE(m[label]) - 2))
    YIELD node
RETURN node
  

Работает как шарм.

Реквизиты для Tore, еще раз спасибо!