选项 1
场景:您想要检索与关键字匹配的所有标签,然后为每个标签检索每个项目(以仍将它们链接到标签的方式)。
首先,这一行:
.StartWithNodeIndexLookup("tags", "tags_fulltext", keyword)
应该是:
.StartWithNodeIndexLookup("tag", "tags_fulltext", keyword)
也就是说,身份应该是tag 而不是tags。这是因为START 子句产生一组节点,每个节点都是tag,而不是一组称为tags 的节点。语义,但它使下一步的事情变得更简单。
现在我们将其称为 tag 而不是 tags,我们将 MATCH 子句更新为:
.Match("tag<-[:TaggedWith]-item")
这就是说“对于集合中的每个标签,去寻找附加到它的每个项目”。同样,“item”是单数。
现在让我们返回它:
.Return((tag, item) => new
{
Tag = tag.As<Tag>(),
Items = item.CollectAs<Item>()
});
在这里,我们将每个“项目”收集到一组“项目”中。我在该代码中对单数与复数的用法非常具体。
生成的 Cypher 表如下所示:
-------------------------
| tag | items |
-------------------------
| red | A, B, C |
| blue | B, D |
| green | E, F, G |
-------------------------
最终代码:
var query = client
.Cypher
.StartWithNodeIndexLookup("tag", "tags_fulltext", keyword)
.Match("tag<-[:TaggedWith]-item")
.Return((tag, item) => new
{
Tag = tag.As<Tag>(),
Items = item.CollectAs<Item>()
});
不过,这不适合您的 SearchResult。
选项 2
场景:您想检索与关键字匹配的所有标签,然后检索与这些标签中的任何一个匹配的所有项目,但您并不关心将两者链接在一起。
让我们回到 Cypher 查询:
START tag=node:tags_fulltext('keyword')
MATCH tag<-[:TaggedWith]-item
RETURN tag, item
这将产生一个像这样的 Cypher 结果表:
--------------------
| tag | item |
--------------------
| red | A |
| red | B |
| red | C |
| blue | B |
| blue | D |
| green | E |
| green | F |
| green | G |
--------------------
您希望将这些中的每一个折叠成一个单独的、不相关的标签和项目列表。
我们可以使用collect 来做到这一点:
START tag=node:tags_fulltext('keyword')
MATCH tag<-[:TaggedWith]-item
RETURN collect(tag) AS Tags, collect(item) AS Items
-----------------------------------------------------------------------------
| tags | items |
-----------------------------------------------------------------------------
| red, red, red, blue, blue, green, green, green | A, B, C, B, D, E, F, G |
-----------------------------------------------------------------------------
我们不希望所有这些重复,所以让我们只收集不同的:
START tag=node:tags_fulltext('keyword')
MATCH tag<-[:TaggedWith]-item
RETURN collect(distinct tag) AS Tags, collect(distinct item) AS Items
--------------------------------------------
| tags | items |
--------------------------------------------
| red, blue, green | A, B, C, D, E, F, G |
--------------------------------------------
在 Cypher 工作的情况下,将其转换为 .NET 很容易:
var query = client
.Cypher
.StartWithNodeIndexLookup("tag", "tags_fulltext", keyword)
.Match("tag<-[:TaggedWith]-item")
.Return((tag, item) => new
{
Tags = tag.CollectDistinct<Tag>(),
Items = item.CollectDistinct<Item>()
});
总结
- 始终从 Cypher 开始
- 始终从 Cypher 开始
- 当您使用 Cypher 时,.NET 实现应该几乎是一对一的
有问题?
我已经在一个不支持 VS 的文本框中输入了所有这些代码,而且我还没有测试过任何代码。如果发生崩溃,请在我们的问题页面上报告完整异常文本和查询。在这里跟踪崩溃很困难。在没有完整异常文本、消息、堆栈跟踪等的情况下跟踪崩溃只会消耗我的时间,因为这会使调试变得更加困难,并且减少了我可以花在帮助您上的时间。