Neo4j APOC назначил триггеры RelationhipProperties, удаленные RelationhipProperties и apoc.index.in
Я использую Neo4j 3.3.5 Community Edition
с APOC apoc-3.3.0.2-all.jar
У меня есть триггеры, которые позволяют мне добавлять / удалять все свойства из определенных отношений в / из индекса вручную:
CALL apoc.trigger.add('HAS_VALUE_ON_CREATED_RELATIONSHIPS_TRIGGER',
'UNWIND {createdRelationships} AS r
MATCH (d:Decision)-[r:HAS_VALUE_ON]->(ch:Characteristic)
CALL apoc.index.addRelationship(r, keys(r)) RETURN count(*)', {phase:'after'})
CALL apoc.trigger.add('HAS_VALUE_ON_DELETED_RELATIONSHIPS_TRIGGER',
\"UNWIND {deletedRelationships} AS r
MATCH (d:Decision)-[r:HAS_VALUE_ON]->(Characteristic)
CALL apoc.index.removeRelationshipByName('HAS_VALUE_ON', r) RETURN count(*)\", {phase:'after'})
Моя бизнес-логика также может вводить новые свойства или удалять существующие из существующих отношений, так что я думаю, чтобы поддерживать свой индекс в актуальном состоянии, я должен также использовать еще два утверждения, например:
assignedRelationshipProperties
removedRelationshipProperties
я прав? Если да, не могли бы вы показать, как их можно использовать для добавления новых триггеров и обновления / удаления свойств в индексе из MATCH (d:Decision)-[r:HAS_VALUE_ON]->(ch:Characteristic)
отношения?
ОБНОВЛЕНИЕ № 1
Я проверил решение, предоставленное в разделе ответов, но, к сожалению, оно не работает. Пожалуйста, смотрите детали ниже:
Я создал следующий триггер:
CALL apoc.trigger.add('TEST_TRIGGER', "UNWIND keys({assignedRelationshipProperties}) AS key
UNWIND {assignedRelationshipProperties}[key] AS map
WITH map
WHERE type(map.relationship) = 'LIVES_IN'
CALL apoc.index.addRelationship(map.relationship, keys(map.relationship))
RETURN count(*)", {phase:'before'})
проверил, что триггер существует CALL apoc.trigger.list()
создать следующие узлы и отношения:
CREATE (p:Person) return p
CREATE (c:City) return c
MATCH (p:Person), (c:City) CREATE (p)-[r:LIVES_IN]->(c) RETURN type(r)
попытался получить к нему доступ с помощью индекса:
MATCH (p:Person)-[r:LIVES_IN]->(c:City)
CALL apoc.index.in(c, 'LIVES_IN', 'time:10') YIELD node AS person
RETURN person
запрос возвращает пустой результат, что пока хорошо.
назначенные отношения новое свойство time
со значением = 10
:
MATCH (p:Person)-[r:LIVES_IN]->(c:City) SET r.time = 10 RETURN r
попытался получить к нему доступ с помощью индекса:
MATCH (p:Person)-[r:LIVES_IN]->(c:City)
CALL apoc.index.in(c, 'LIVES_IN', 'time:10') YIELD node AS person
RETURN person
запрос успешно возвращает ожидаемый Person
узел
Теперь я переназначил time
свойство другое значение = 11
MATCH (p:Person)-[r:LIVES_IN]->(c:City) SET r.time = 11 RETURN r
попытался получить к нему доступ по индексу еще раз:
MATCH (p:Person)-[r:LIVES_IN]->(c:City)
CALL apoc.index.in(c, 'LIVES_IN', 'time:10') YIELD node AS person
RETURN person
MATCH (p:Person)-[r:LIVES_IN]->(c:City)
CALL apoc.index.in(c, 'LIVES_IN', 'time:11') YIELD node AS person
RETURN person
запрос возвращает пустой результат для них обоих..
Почему индекс не обновлялся после изменения свойства?
ОБНОВЛЕНИЕ № 2
Я создал следующий триггер:
CALL apoc.trigger.add('HAS_VALUE_ON_ASSIGNED_RELATIONSHIP_PROPERTIES_TRIGGER',
"UNWIND apoc.trigger.propertiesByKey({assignedRelationshipProperties}, 'time') AS prop WITH prop.relationship as r
CALL apoc.index.addRelationship(r, keys(r))
RETURN count(*)", {phase:'after'})
проверил, что триггер существует CALL apoc.trigger.list()
создать следующие узлы и отношения:
CREATE (p:Person) return p
CREATE (c:City) return c
MATCH (p:Person), (c:City) CREATE (p)-[r:LIVES_IN]->(c) RETURN type(r)
попытался получить к нему доступ с помощью индекса:
MATCH (p:Person)-[r:LIVES_IN]->(c:City)
CALL apoc.index.in(c, 'LIVES_IN', 'time:10') YIELD node AS person
RETURN person
запрос возвращает пустой результат, который пока хорош.
назначенные отношения новое свойство time
со значением = 10
:
MATCH (p:Person)-[r:LIVES_IN]->(c:City) SET r.time = 10 RETURN r
попытался получить к нему доступ с помощью индекса:
MATCH (p:Person)-[r:LIVES_IN]->(c:City)
CALL apoc.index.in(c, 'LIVES_IN', 'time:10') YIELD node AS person
RETURN person
запрос успешно возвращает ожидаемый Person
узел
Теперь я переназначил time
свойство другое значение = 11
MATCH (p:Person)-[r:LIVES_IN]->(c:City) SET r.time = 11 RETURN r
попытался получить к нему доступ по индексу еще раз:
MATCH (p:Person)-[r:LIVES_IN]->(c:City)
CALL apoc.index.in(c, 'LIVES_IN', 'time:10') YIELD node AS person
RETURN person
MATCH (p:Person)-[r:LIVES_IN]->(c:City)
CALL apoc.index.in(c, 'LIVES_IN', 'time:11') YIELD node AS person
RETURN person
запрос возвращает пустой результат для них обоих..
Таким образом, этот подход столкнулся с той же проблемой, что я описал выше. И другой недостаток заключается в том, что мне нужно указать точное имя ключа - в этом случае time
, Но я не заинтересован в каком-то определенном ключе, но вместо этого меня интересует добавление / обновление / удаление всех ключей HAS_VALUE_ON
отношения.
2 ответа
assignedRelationshipProperties
довольно сложно. Структура этого параметра Map<String, List<Map<String, Object>>>
,
Где первый String
является ключом свойства, а элементы списка являются картами со следующими ключами:
- ключ: ключ свойства
- old: старое значение, если есть
- new: новое значение, присвоенное свойству
- отношения: отношения, о которых идет речь
Чтобы быть более наглядным, этот параметр выглядит в формате отладки:
Для вашего конкретного случая использования, обновляя индекс lucene при обновлении свойств отношений для определенного типа отношений, вы можете использовать следующий запрос:
CALL apoc.trigger.add('test-rel-trigger',
'UNWIND keys({assignedRelationshipProperties}) AS key
UNWIND {assignedRelationshipProperties}[key] AS map
WITH map WHERE type(map.relationship) = "HAS_VALUE_ON"
CALL apoc.index.addRelationship(map.relationship, keys(map.relationship)) RETURN count(*)'
, {phase:'before'})
Что касается удаления, поскольку вы индексируете полную карту свойств, я полагаю, вы можете просто заменить assignedRelationshipProperties
с removedRelationshipProperties
Существуют специальные вспомогательные функции для их использования, которые описаны в документации для доступа к узлам / зависимостям или свойствам этих структур данных:
см.: https://neo4j-contrib.github.io/neo4j-apoc-procedures/
Таблица 4. Вспомогательные функции
apoc.trigger.nodesByLabel({assignedLabels/assignedNodeProperties},'Label')
функция для фильтрации labelEntries по метке, которая будет использоваться внутри оператора триггера с {assignedLabels}
а также {removedLabels}
{phase:'before/after/rollback'}
возвращает предыдущую и новую информацию о триггере
apoc.trigger.propertiesByKey({assignedNodeProperties},'key')
функция для фильтрации propertyEntries по ключу свойства, которая будет использоваться в операторе триггера с {assignedNode/RelationshipProperties}
а также {removedNode/RelationshipProperties}
,
Возвращает [{old,[new],key,node,relationship}]