【问题标题】:Unable to remove a node from Neo4j Spatial index无法从 Neo4j 空间索引中删除节点
【发布时间】:2016-06-05 22:04:32
【问题描述】:

在我的TransactionEventHandler.beforeCommit() 中,我试图在成功添加节点后从空间索引中删除它。但是该节点仍保留在索引中,我仍然能够使用空间密码查询找到它。

这是我的代码的摘录:

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。

我找到了解决方案(解决方法):

William Lyon 阐明了一些情况:

当使用空间索引将节点添加到空间索引时 IndexProvider 接口它创建一个代理节点并将该节点添加到 空间索引,保持原始节点与 图内 RTree 索引。

我发现,代理节点总是包含一个“id”属性。它指向原始节点。我们甚至不需要手动添加它(正如 William 所提议的那样)。使用它我们可以找到代理节点以便手动删除它。

有时我们的图表可能如下所示:

有时它可能会变得有点复杂:

在图片上:

  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);
}

【问题讨论】:

  • 你能分享你用来将节点添加到索引的代码吗?以及INDEX_NAMECONFIG 的值?
  • @WilliamLyon 您已经在查看此代码:我正在将节点添加到以下行中的索引:index.add(node, null, null); INDEX_NAME 只是一个字符串“位置”;而CONFIG 就是SpatialIndexProvider.SIMPLE_POINT_CONFIG
  • @WilliamLyon 我在问题中添加了信息。请看一下。我相信,这可能有助于更好地了解我的情况。提前致谢。
  • 现在找到解决方案(解决方法)。它在我的问题下进行了描述。

标签: neo4j spatial spatial-index


【解决方案1】:

当使用空间 IndexProvider 接口将节点添加到空间索引时,它会创建一个 代理 节点并将 那个 节点添加到空间索引,保持原始节点分开来自图内 RTree 索引。

这与空间库的其他接口不一致,造成了一些混乱。请参阅this SO post 了解更多信息。

您可以向要索引的节点添加一个 id 属性,以便在您想从索引中删除它时找到代理节点,或者使用空间 Java API 从空间层添加/删除节点以避免创建代理节点。

【讨论】:

  • 谢谢!您的回答为我指明了正确的方向。最后我能够删除代理节点。我在我的问题下描述了我的解决方案。但我仍然不明白为什么简单的index.remove(node); 不起作用。我一直使用它与index.add(node, null, null);。似乎它必须工作,这种行为是一个错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-17
  • 2014-11-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-15
相关资源
最近更新 更多