Невозможно удалить узел из пространственного индекса Neo4j

Внутри моего TransactionEventHandler.beforeCommit() Я пытаюсь удалить узел из пространственного индекса, после того, как он был успешно добавлен. Но узел остается в индексе, и я все еще могу найти его, используя пространственный запрос Cypher.

Это выдержка из моего кода:

Index<Node> index = getGraphDatabaseService().index().forNodes("locations", SpatialIndexProvider.SIMPLE_POINT_CONFIG);
if (node.hasProperty("lat") && node.hasProperty("lon")) {
    index.add(node, null, null); // it works perfectly
} else {
    index.remove(node); // it doesn't work
}

Это известная ошибка в Neo4j Spatial? Во всяком случае, как я могу достичь своей цели?

PS: я использую Neo4j 2.3.2 и Neo4j Spatial 0.15-neo4j-2.3.1.

Я нашел решение (обходной путь):

Уильям Лион пролил некоторый свет на ситуацию:

Когда узел добавляется к пространственному индексу с использованием пространственного интерфейса IndexProvider, он создает прокси-узел и добавляет этот узел к пространственному индексу, оставляя исходный узел отделенным от индекса RTree в графе.

Я обнаружил, что прокси-узел всегда содержит свойство "id". Это указывает на оригинальный узел. Нам даже не нужно добавлять его вручную (как было предложено Уильямом). Используя его, мы можем найти прокси-узел, чтобы удалить его вручную.

Иногда наш график может выглядеть так:

введите описание изображения здесь

И иногда это может стать немного сложнее:

введите описание изображения здесь

На изображениях:

  1. Пространственный корень (узел с меткой "ReferenceNode"), помеченный как "1"
  2. Прокси-узел выбран

Итак, мы можем использовать следующий Cypher-запрос, чтобы найти и удалить прокси-узел:

MATCH (:ReferenceNode)-[:LAYER]-()-[:RTREE_ROOT]-()-[*..]-(n {id:{id}}) MATCH (n)-[r:RTREE_REFERENCE]-() DELETE r, n

И вот полное решение, которое я сейчас использую в своем TransactionEventHandler :

private static final String INDEX_NAME = "locations";
private static final Map<String, String> CONFIG = SpatialIndexProvider.SIMPLE_POINT_CONFIG;
private static final String LAT = CONFIG.get(LayerNodeIndex.LAT_PROPERTY_KEY);
private static final String LON = CONFIG.get(LayerNodeIndex.LON_PROPERTY_KEY);

@Override
public Void beforeCommit(TransactionData data) throws Exception {
    Index<Node> index = getGraphDatabaseService().index().forNodes(INDEX_NAME, CONFIG);
    Node originalNode = <...>;
    if (originalNode.hasProperty(LAT) && originalNode.hasProperty(LON)) {
        index.add(originalNode, null, null);
    } else {
        deleteProxyNode(originalNode.getId());
    }
    return null;
}

private void deleteIndexedProxyNode(long originalNodeId) {
    String query = "" +
            "MATCH (:ReferenceNode)-[:LAYER]-()-[:RTREE_ROOT]-()-[*..]-(n {id:{id}}) " +
            "MATCH (n)-[r:RTREE_REFERENCE]-() " +
            "DELETE r, n";
    Map<String, Object> parameters = new HashMap<>();
    parameters.put("id", originalNodeId);
    getGraphDatabaseService().execute(query, parameters);
}

1 ответ

Решение

Когда узел добавляется к пространственному индексу с использованием пространственного интерфейса IndexProvider, он создает прокси- узел и добавляет этот узел к пространственному индексу, оставляя исходный узел отделенным от индекса RTree в графе.

Это не согласуется с другими интерфейсами для пространственной библиотеки и вызвало некоторую путаницу. Смотрите этот пост так, чтобы получить больше информации.

Вы можете добавить свойство id к индексируемому узлу, чтобы иметь возможность найти прокси-узел, когда вы хотите удалить его из индекса, или использовать пространственный API Java для добавления / удаления узлов из пространственного слоя, чтобы избежать создания прокси узел.

Другие вопросы по тегам