【问题标题】:how can I return two collections with a cypher query in the neo4j .net client如何在 neo4j .net 客户端中使用密码查询返回两个集合
【发布时间】:2013-03-27 12:05:35
【问题描述】:

我想在一个查询“标签”和“项目”中返回两个集合,其中每个标签可以有 0.. 多个项目。看起来如果我使用投影,它将假设一个包含两列而不是两个集合的集合,对吗?有没有更好的方法来运行这个搜索查询?

我收到"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()
};

【问题讨论】:

    标签: neo4jclient


    【解决方案1】:

    选项 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>()
        });
    

    总结

    1. 始终从 Cypher 开始
    2. 始终从 Cypher 开始
    3. 当您使用 Cypher 时,.NET 实现应该几乎是一对一的

    有问题?

    我已经在一个不支持 VS 的文本框中输入了所有这些代码,而且我还没有测试过任何代码。如果发生崩溃,请在我们的问题页面上报告完整异常文本和查询。在这里跟踪崩溃很困难。在没有完整异常文本、消息、堆栈跟踪等的情况下跟踪崩溃只会消耗我的时间,因为这会使调试变得更加困难,并且减少了我可以花在帮助您上的时间。

    【讨论】:

    • 感谢您详尽的撰写。另一个转折:使用选项 2,我将如何返回与项目没有任何 taggedwith 关系的标签集?只有当它们与索引搜索匹配并且它们没有任何项目时,它才是标签。项目集合仍将返回其标签与索引查询匹配的项目。
    • 令人印象深刻的答案,@TathamOddie !
    • 测试它,在.net 翻译位我只看到一个 CollectDistinctAs> 方法而不是 CollectDistinct 。我想返回一个 POCO 对象,所以不想要 Node 结果。我错过了正确的方法吗?我是否应该像 CollectDistinctAs>().Select((node) => node.Data) 一样在其末尾添加一个选择投影
    • 我们不能只检索数据,Cypher 为我们提供了完整的节点。稍后您需要将其投影。
    猜你喜欢
    • 1970-01-01
    • 2022-11-25
    • 1970-01-01
    • 1970-01-01
    • 2012-12-29
    • 2015-12-22
    • 1970-01-01
    • 1970-01-01
    • 2021-07-19
    相关资源
    最近更新 更多