使用聚合框架,我如何使用管道中的数据修饰 MongoDB 中的集合(有点右外连接)

Using the Aggregate Framework, how can I embelish a Collection in MongoDB with data from a pipeline (kinda right outer join)

db.Parent.insertMany([
{ParentName: "MS", Type: "TAA"},
{ParentName: "MS", Type: "TAB"},
{ParentName: "MS", Type: "TAC"},
{ParentName: "MS", Type: "TAD"},
{ParentName: "GP", Type: "TAA"},
{ParentName: "GP", Type: "TAB"},
{ParentName: "GP", Type: "TAC"},
])

db.Mapper.insertMany([
{Type: "TAA", Identifier: "RA"},
{Type: "TAB", Identifier: "SA"},
{Type: "TAC", Identifier: "TA"},
{Type: "TAD", Identifier: "WA"},
])

db.Items.insertMany ([
{Name: "One", Identifier: "RA"},
{Name: "Two", Identifier: "RA"},
{Name: "Three", Identifier: "RA"},
{Name: "Four", Identifier: "SA"},
{Name: "Five", Identifier: "SA"},
{Name: "Six", Identifier: "WA"},
])

对于“GP”的给定输入参数,我想用 Parent 中的 Type 修饰 Items, 通过Mapper映射,输出如下。我想要所有物品,不管 是否有来自 Parent/Mapper 的匹配项。

[
{Name: "One",  Identifier: "RA", Type: "TAA"},
{Name: "Two",  Identifier: "RA", Type: "TAA"},
{Name: "Three",Identifier: "RA", Type: "TAA"},
{Name: "Four", Identifier: "SA", Type: "TAB"},
{Name: "Five", Identifier: "SA", Type: "TAB"},
{Name: "Six",  Identifier: "WA},
]

对于 Parent 中给定的“GP”输入,我从 Mapper 中选择了正确的行,但一直卡在那里。

我不确定是否可以切换查询并从 Items 开始,然后插入任何匹配项。

db.Parent.aggregate(
{$match: {ParentName: "GP}},
{$project: {Type:1, _id:0}},
{$group: {_id:1, types: {$addToSet: "$Type"}}},
{$lookup: {
  from: "Mapper",
  let: {types: "$types"},
  pipeline:[{
    $match: {$expr: {$in: ["$Type", "$$types"]}}    
  }],
  as: "mapper"
}},
??? Right outer join with Items here ???
).pretty()

查询 1

  • 非嵌套连接(先展开)
  • lookup MapperIdentifier
  • unwindproject 只保留我们需要的东西
  • lookup with Parent with 2 creterias
    • "$ParentName" = "GP"
    • and same Type
  • unwindpreserveNullAndEmptyArrays 以保留未加入的人
  • project只保留需要的东西

Test code here

items.aggregate(
[{"$lookup": 
    {"from": "Mapper",
      "localField": "Identifier",
      "foreignField": "Identifier",
      "as": "joined"}},
  {"$unwind": {"path": "$joined"}},
  {"$project": {"Type": "$joined.Type", "Name": 1, "Identifier": 1}},
  {"$lookup": 
    {"from": "Parent",
      "let": {"type": "$Type", "indentifier": "$Identifier"},
      "pipeline": 
      [{"$match": 
          {"$expr": 
            {"$and": 
              [{"$eq": ["$ParentName", "GP"]}, {"$eq": ["$$type", "$Type"]}]}}},
        {"$set": {"Identifier": "$$indentifier"}}],
      "as": "joined"}},
  {"$unwind": {"path": "$joined", "preserveNullAndEmptyArrays": true}},
  {"$project": 
    {"_id": 0, "Name": 1, "Identifier": "$joined.Identifier", "Type": 1}}])

查询2

  • 嵌套连接
  • 加入itemIndetifier
  • 仅当 ParentName="GP"
  • 时嵌套连接类型
  • 像上面那样使用 preserveNullAndEmptyArrays 选项放松
  • 最终解除
  • 保留我们需要的项目

Test code here

items.aggregate(
[{"$lookup": 
    {"from": "Mapper",
      "let": {"itemIndetifier": "$Identifier"},
      "pipeline": 
      [{"$match": {"$expr": {"$eq": ["$$itemIndetifier", "$Identifier"]}}},
        {"$lookup": 
          {"from": "Parent",
            "let": {"type": "$Type"},
            "pipeline": 
            [{"$match": 
                {"$expr": 
                  {"$and": 
                    [{"$eq": ["$ParentName", "GP"]},
                      {"$eq": ["$$type", "$Type"]}]}}}],
            "as": "joined1"}},
        {"$unwind": 
          {"path": "$joined1", "preserveNullAndEmptyArrays": true}}],
      "as": "joined2"}},
  {"$unwind": {"path": "$joined2"}},
  {"$project": 
    {"_id" : 0,"Name": 1, "Identifier": 1, "Type": "$joined2.joined1.Type"}}])

*用于管道查找的索引你需要 MongoDB 5,如果你对你的数据进行基准测试,请发送一些反馈,如果可以的话,哪个更快。我认为这两个查询都能满足您的需求。