#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, еще раз спасибо!