草庐IT

mongodb - 在 $lookup 之后将原始对象数组合并到 "as"字段中

coder 2023-11-03 原文

我有一个 hero 集合,其中每个 hero 文档如下所示:

{
    _id:'the-name-of-the-hero',
    name: 'Name of Hero',
    (...), //other properties to this hero

    relations: [
        {
            hero: 'the-id-of-another-hero',
            relationType: 'trust'
        },
        {
            hero: 'yet-another-id-of-another-hero',
            relationType: 'hate'
        }
    ]
}

relations.hero 指向另一个英雄的 _id。我需要获取更多相关英雄的信息,因此我使用聚合 $lookup 将每个英雄与“英雄”集合进行匹配,以获取它的 name(和其他数据,但针对问题简化了项目)。这里是当前工作的查询,记录在案:

let aggregate = db.collection('hero').aggregate([
    // grabbing an specific hero
    { $match: { _id } },
    //populate relations
    {
        $lookup: {
            from: 'hero',
            let: { letId: '$relations.hero' }, //create a local variable for the pipeline to use
            // localField: "relations.hero", //this would bring entire hero data, which is unnecessary
            // foreignField: "_id",  //this would bring entire hero data, which is unnecessary
            pipeline: [
                //match each $relations.hero (as "$$letId") in collection hero's (as "from") $_id
                { $match: { $expr: { $in: ['$_id', '$$letId'] } } },
                //grab only the _id and name of the matched heroes
                { $project: { name: 1, _id: 1 } },
                //sort by name
                { $sort:{ name: 1 } }
            ],
            //replace the current relations with the new relations
            as: 'relations',
        },
    }
]).toArray(someCallbackHere);

简而言之,$lookuphero 集合上使用 pipeline 匹配每个 relations.hero 和只带回 _idname(在 UI 上打印真实姓名)并用这个新的 替换当前的 relations关系,生成文档为:

{
    _id:'the-name-of-the-hero',
    name: 'Name of Hero',
    (...), //other properties to this hero
    relations: [
        {
            _id: 'the-id-of-another-hero',
            name: 'The Real Name of Another Hero',
        },
        {
            _id: 'yet-another-id-of-another-hero',
            name: 'Yet Another Real Name of Another Hero',
        }
    ]
}

问题:

我可以在管道上添加什么以使其将匹配的英雄与原始 relations 合并,以便不仅具有投影的 _idname ,还有原来的relationType?即有如下结果:

{
    _id:'the-name-of-the-hero',
    name: 'Name of Hero',
    (...), //other properties to this hero
    relations: [
        {
            _id: 'the-id-of-another-hero',
            name: 'The Real Name of Another Hero',
            relationType: 'trust' //<= kept from the original relations
        },
        {
            _id: 'yet-another-id-of-another-hero',
            name: 'Yet Another Real Name of Another Hero',
            relationType: 'hate' //<= kept from the original relations
        }
    ]
}

我尝试将 导出为:'relationsFull',然后尝试将 $push$mergeObjects 作为聚合下一步的一部分但没有运气。我尝试做与管道步骤相同的操作(而不是新的聚合步骤),但总是以 relations 为空数组结束..

我将如何编写一个新的聚合步骤来将旧的 relations 对象与新查找的 relations 对象合并?

注意:考虑 MongoDB 3.6 或更高版本(即,不需要 $unwind 数组,至少对于 $lookup).如果该信息很重要,我正在使用 Node.js 驱动程序进行查询。

最佳答案

您可以使用以下聚合

db.collection("hero").aggregate([
  { "$match": { _id } },
  { "$unwind": "$relations" },
  { "$lookup": {
    "from": "hero",
    "let": { "letId": "$relations.hero" },
    "pipeline": [
      { "$match": { "$expr": { "$eq": ["$_id", "$$letId"] } } },
      { "$project": { "name": 1 } }
    ],
    "as": "relation"
  }},
  { "$unwind": "$relation" },
  { "$addFields": { "relations.name": "$relation.name" }},
  { "$group": {
    "_id": "$_id",
    "relations": { "$push": "$relations" },
    "name": { "$first": "$name" },
    "rarity": { "$first": "$rarity" },
    "classType": { "$first": "$classType" }
  }}
])

或者你也可以使用它

db.collection("hero").aggregate([
  { "$match": { _id } },
  { "$lookup": {
    "from": "hero",
    "let": { "letId": "$relations.hero" },
    "pipeline": [
      { "$match": { "$expr": { "$in": ["$_id", "$$letId"] } } },
      { "$project": { "name": 1 } }
    ],
    "as": "lookupRelations"
  }},
  { "$addFields": {
    "relations": {
      "$map": { 
        "input": "$relations",
        "as": "rel",
        "in": {
          "$mergeObjects": [
            "$$rel",
            { "name": { "$arrayElemAt": ["$lookupRelations.name", { "$indexOfArray": ["$lookupRelations._id", "$$rel._id"] }] }}
          ]
        }
      }
    }
  }}
])

关于mongodb - 在 $lookup 之后将原始对象数组合并到 "as"字段中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54832677/

有关mongodb - 在 $lookup 之后将原始对象数组合并到 "as"字段中的更多相关文章

  1. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  2. ruby-on-rails - rails : "missing partial" when calling 'render' in RSpec test - 2

    我正在尝试测试是否存在表单。我是Rails新手。我的new.html.erb_spec.rb文件的内容是:require'spec_helper'describe"messages/new.html.erb"doit"shouldrendertheform"dorender'/messages/new.html.erb'reponse.shouldhave_form_putting_to(@message)with_submit_buttonendendView本身,new.html.erb,有代码:当我运行rspec时,它失败了:1)messages/new.html.erbshou

  3. ruby-on-rails - 由于 "wkhtmltopdf",PDFKIT 显然无法正常工作 - 2

    我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-

  4. ruby-on-rails - 按天对 Mongoid 对象进行分组 - 2

    在控制台中反复尝试之后,我想到了这种方法,可以按发生日期对类似activerecord的(Mongoid)对象进行分组。我不确定这是完成此任务的最佳方法,但它确实有效。有没有人有更好的建议,或者这是一个很好的方法?#eventsisanarrayofactiverecord-likeobjectsthatincludeatimeattributeevents.map{|event|#converteventsarrayintoanarrayofhasheswiththedayofthemonthandtheevent{:number=>event.time.day,:event=>ev

  5. ruby-on-rails - 结合 meta_search 与 acts_as_taggable_on - 2

    我在开发的Rails3网站的一些搜索功能上遇到了一个小问题。我有一个简单的Post模型,如下所示:classPost我正在使用acts_as_taggable_on来更轻松地向我的帖子添加标签。当我有一个标记为“rails”的帖子并执行以下操作时,一切正常:@posts=Post.tagged_with("rails")问题是,我还想搜索帖子的标题。当我有一篇标题为“Helloworld”并标记为“rails”的帖子时,我希望能够通过搜索“hello”或“rails”来找到这篇帖子。因此,我希望标题列的LIKE语句与acts_as_taggable_on提供的tagged_with方法

  6. ruby - 检查 "command"的输出应该包含 NilClass 的意外崩溃 - 2

    为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar

  7. ruby-on-rails - 如何验证非模型(甚至非对象)字段 - 2

    我有一个表单,其中有很多字段取自数组(而不是模型或对象)。我如何验证这些字段的存在?solve_problem_pathdo|f|%>... 最佳答案 创建一个简单的类来包装请求参数并使用ActiveModel::Validations。#definedsomewhere,atthesimplest:require'ostruct'classSolvetrue#youcouldevencheckthesolutionwithavalidatorvalidatedoerrors.add(:base,"WRONG!!!")unlesss

  8. ruby-on-rails - form_for 中不在模型中的自定义字段 - 2

    我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢

  9. Ruby 写入和读取对象到文件 - 2

    好的,所以我的目标是轻松地将一些数据保存到磁盘以备后用。您如何简单地写入然后读取一个对象?所以如果我有一个简单的类classCattr_accessor:a,:bdefinitialize(a,b)@a,@b=a,bendend所以如果我从中非常快地制作一个objobj=C.new("foo","bar")#justgaveitsomerandomvalues然后我可以把它变成一个kindaidstring=obj.to_s#whichreturns""我终于可以将此字符串打印到文件或其他内容中。我的问题是,我该如何再次将这个id变回一个对象?我知道我可以自己挑选信息并制作一个接受该信

  10. ruby-on-rails - 如果 Object::try 被发送到一个 nil 对象,为什么它会起作用? - 2

    如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象

随机推荐