neo4j - 如何处理密码查询常见节
问题描述
我正在编写一堆查询以便在 Neo4j 中构建一棵树,但是为了添加不同类型的新数据,我正在为每个查询编写相同的开头节。
示例:我希望能够在Root(identifier=Root1)->A(identifier=1)->B(identifier=2)...
不修改其他根指向的树的情况下添加。
我所有的查询都是从
Match
(root:`Root` {identifier=$identifier})
Create
(root)-[:`someRel`]->(a:`A` {identifier=$a_identifier})
然后过了一段时间,A 需要一个孩子:
Match
(root:`Root` {identifier=$identifier})
-[:`someRel`]->
(a:`A` {identifier=$a_identifier})
Create
(a)-[:`someOtherRel`]->(b:`B` {identifier=$b_identifier})
然后又过了一段时间,也许 B 需要一个孩子,我必须使用相同的开头节来到达 A,然后再添加一个以得到正确的 B。
是否有一些我缺少的功能可以让我不必在每次我想要到达正确的 B(或 C 或 D)时建立那些开头的节,或者我只需要使用字符串连接来做到这一点?
字符串连接示例:(python)
MATCH
{ROOT_LOOKUP_STANZA},
{A_LOOKUP_STANZA},
{B_LOOKUP_STANZA},
CREATE
(b)-[:`c_relationship`]->(c:`C` {...})
一些附加说明:
- 根节点必须唯一标识
- 其余节点必须与其父节点唯一标识。所以以下是有效的:
Root(root)->A(a)->B(b)
Root(root)->A(a1)->B(b)
在这种情况下,B(b) 引用了两个不同的节点,因为它们的父节点不同。
解决方案
所以你的主要问题是孩子没有唯一的ID,只有根节点有唯一的ID。Neo4j 没有任何机制(还)将一个查询的最终上下文携带到另一个查询的开头,并且不保证节点内部 id 在查询之间是相同的。因此,对于您的数据,您必须匹配整个链以确保匹配要附加到的正确节点。不过,您可以做一些事情来使这变得不必要。
添加一个 UUID
通过向每个节点添加一个普遍唯一的 id(并对该属性进行索引),您将能够在该 id 上进行匹配,并保证没有冲突,并且在查询中它是相同的。任何时候使用节点内部 ID 都会很有用,这是您可以在数据中使用 UUID 的好兆头。(如果数据被镜像到其他数据库也有帮助)
将路径存储为唯一 ID
您可能不知道在 Neo4j 中分配的 UUID(因为它不在源数据中),但在树中您可以创建一个唯一的 ID,格式为<parent-ID>_<index><sorted-labels><source-id>
. 这里的想法是保证父级有一个唯一的 id,并且您将该 id 与使该子级对该父级唯一的信息相结合。这允许您生成确定性的唯一 ID。(需要一个树数据结构,具有唯一的根 id)在大多数情况下,您可以不考虑索引部分(即源数据中的列表/数组的情况)。本质上,您将从根节点到该节点的路径存储为节点唯一 ID。(同样,您将需要此 id 的索引)
批处理作业
如果这只是一项工作的一部分,另一种选择是将您想要进行的更改集中起来,并生成一个密码来完成所有这些,而 Neo4j 已经获取了所有内容。
推荐阅读
- c++ - `std::wregex` 是否支持 utf-16/unicode 或仅支持 UCS-2?
- mongodb - 为什么@Indexed 不在 MongoDB 中创建索引?(MongoDB、Morphia、Spring Data)
- android - React Native Facebook SDK 登录 - 登录时应用程序崩溃
- javascript - 设置 maxzoom 和 minzoom 属性
- macos - NSSplitView 屏幕伪像
- serverless - 无服务器脱机无法脱机运行:无法加载资源:net::ERR_CONNECTION_REFUSED
- amazon-web-services - 为每个 API 资源调用相同的 lambda 函数
- assembly - 从键盘读取并写入文件(emu8086)
- typescript - 在打字稿中声明对象类型
- android - Webview 不是可滚动的android