Neo4j найти все узлы с соответствующими свойствами
У меня относительно большой набор узлов, и я хочу найти все пары узлов, которые имеют соответствующие значения свойств, но я не знаю и не забочусь заранее, что такое значение свойства. Это в основном попытка найти дублирующие узлы, но я могу ограничить определение дубликата двумя или более узлами, которые имеют одно и то же значение свойства.
Любые идеи о том, как действовать? Не находить начальных точек в документах neo4j. Я участвую в выпуске сообщества 1.8.2.
ИЗМЕНИТЬ
Извините за то, что вы не поняли начальный вопрос, но я говорю об этом через Cypher.
Ответы
Ответ 1
Cypher для подсчета значений свойства, возвращая также набор узлов:
start n=node(*)
where has(n.prop)
with n.prop as prop, collect(n) as nodelist, count(*) as count
where count > 1
return prop, nodelist, count;
Пример консоли: http://console.neo4j.org/r/k2s7aa
Вы также можете выполнить сканирование индекса с таким свойством (чтобы не смотреть на узлы, которые не имеют этого свойства):
start n=node:node_auto_index('prop:*') ...
2.0 Cypher с меткой Метка:
match (n:Label)
with n.prop as prop, collect(n) as nodelist, count(*) as count
where count > 1
return prop, nodelist, count;
Ответ 2
Как насчет следующего подхода:
- используйте getAllNodes, чтобы получить итерацию по всем узлам.
- используя getPropertyKeys и getProperty (ключ) создайте
java.util.Map
, содержащий все свойства для node. Вычислить карту hashCode()
- создайте глобальный
Map
, используя ключ hashCode as и набор node.getId()
как значения
Это должно дать вам кандидатов для дублирования. Помните о семантике hashCode(), там могут быть узлы с различным сопоставлением свойств для одного и того же хэш-кода.
Ответ 3
Вы можете попробовать этого, кто делает то, что я думаю, делает все, что вы хотите.
START n=node(*), m=node(*)
WHERE
HAS(n.name) AND HAS (m.name) AND
n.name=m.name AND
ID(n) <ID(m)
RETURN n, m
http://console.neo4j.org/?id=xe6wmt
Оба узла должны иметь свойство name
. name
должен быть равен для обоих узлов, и нам нужна только одна пара двух возможных, которые мы получаем через сравнение id. Не уверен в производительности - пожалуйста, проверьте.
Ответ 4
Самый лучший/самый простой вариант - сделать что-то вроде локального Map
. Если вы сделали что-то подобное, вы можете создать такой код:
GlobalGraphOperations ggo = GlobalGraphOperations.at(db);
Map<Object, Node> duplicateMap = new HashMap<Object, Node>();
for (Node node : ggo.getAllNodes()) {
Object propertyValue = node.getProperty("property");
Node existingNode = duplicateMap.get(propertyValue);
if (existingNode == null) {
duplicateMap.put(propertyValue, node);
} else {
System.out.println("Duplicate Node. First Node: " + existingNode + ", Second Node: " + node);
}
}
Это приведет к распечатке списка. Если вам нужно сделать больше, например удалить эти узлы, вы можете сделать что-то в другом.
Знаете ли вы название свойства? Будет ли это несколько свойств или просто дубликатов одной пары имя/значение? Если вы выполняете несколько свойств, просто создайте карту для каждого свойства, которое у вас есть.
Ответ 5
Вы также можете использовать индекс для этого свойства. Затем для данного значения извлекают все узлы. Преимущество состоит в том, что вы также можете запросить приблизительные значения.
Ответ 6
Neo4j 3.1.1
HAS больше не поддерживается в Cypher, вместо этого используйте EXISTS.
Если вы хотите найти узлы с определенным свойством, Cyper выглядит следующим образом:
MATCH (n:NodeLabel) where has(n.NodeProperty) return n