我想在一个查询“tags”和“items”中返回两个集合,其中每个标记可以包含0..many项。看起来如果我使用投影,它会假设一个集合有两列而不是两个集合,这是正确的吗?有没有更好的方法来运行此搜索查询?
我正在"the query response contains columns Tags, Items however ...anonymous type does not contain settable properties to receive this data"
var query = client
.Cypher
.StartWithNodeIndexLookup("tags", "tags_fulltext", keyword)
.Match("tags<-[:TaggedWith]-items")
.Return((items, tags) => new
{
Tags = tags.As<Tag>(),
Items = items.As<Item>()
});
var results = await query.ResultsAsync;
return new SearchResult
{
Items = results.Select(x => x.Items).ToList(),
Tags = results.Select(x => x.Tags).Distinct().ToList()
};
答案 0 :(得分:3)
场景:您想要检索与关键字匹配的所有标记,然后为每个标记检索每个项目(以某种方式仍然将它们链接到标记)。
首先,这一行:
.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>()
});
在这里,我们将每个'item'和收集它们放入一组'items'中。我在该代码中对单数与复数的使用是非常具体的。
生成的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
。
场景:您想要检索与关键字匹配的所有标记,然后检索与这些标记中的任何标记匹配的所有项目,但您不必关心将这两个标记链接在一起。< / p>
让我们回到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>()
});
我在没有VS支持的文本框中输入了所有这些代码,我还没有测试过任何代码。如果出现问题,请在我们的问题页面上报告完整例外文字和查询。在这里跟踪崩溃很难。在没有完整异常文本,消息,堆栈跟踪等情况下跟踪崩溃只会耗费我的时间,使调试更加困难,并减少我可以花费多少时间来帮助您。