【问题标题】:Aggregate with lookup and contcat Strings in MongoDb在 MongoDb 中使用查找和连接字符串进行聚合
【发布时间】:2020-04-09 14:23:11
【问题描述】:

我有两个收藏events & members

事件架构:

{
   name : String,
   members: [{status : Number, memberId : {type: Schema.Types.ObjectId, ref: 'members'}]
}

事件示例文档:

"_id" : ObjectId("5e8b0bac041a913bc608d69d")
  "members" : [ 
        {
            "status" : 4,
            "_id" : ObjectId("5e8b0bac041a913bc608d69e"),
            "memberId" : ObjectId("5e7dbf5b257e6b18a62f2da9"),
            "date" : ISODate("2020-04-06T10:59:56.997Z")
        }, 
        {
            "status" : 1,
            "_id" : ObjectId("5e8b0bf2041a913bc608d6a3"),
            "memberId" : ObjectId("5e7e2f048f80b46d786bfd67"),
            "date" : ISODate("2020-04-06T11:01:06.463Z")
        }
    ],

成员架构:

{
  firstname : String
  photo  : String
} 

成员示例文档:

  [{
        "_id" : ObjectId("5e7dbf5b257e6b18a62f2da9"),
        "firstname" : "raed",
        "photo" : "/users/5e7dbf5b257e6b18a62f2da9/profile/profile-02b13aef6e.png"
    }, 
    {
        "_id" : ObjectId("5e7e2f048f80b46d786bfd67"),
        "firstname" : "sarra",
        "photo" : "/5e7e2f048f80b46d786bfd67/profile/profile-c79f91aa2e.png"
    }]

我使用聚合进行查询,并查找以获取成员的填充数据,并且我想通过字符串连接成员的照片字段,但出现错误, 我该怎么做?

查询:

db.getCollection('events').aggregate([
        { $match: { _id: ObjectId("5e8b0bac041a913bc608d69d")}},
        {
            "$lookup": {
                "from": "members",
                "localField": "members.memberId",
                "foreignField": "_id",
                "as": "Members"
            }
        },
        {
            $project: {
                "Members.firstname" : 1,
                "Members.photo": 1,
                //"Members.photo": {$concat:["http://myurl", "$Members.photo"]},
                "Members._id" : 1,
                },

        }
    ])

没有 concat 的结果:

{
    "_id" : ObjectId("5e8b0bac041a913bc608d69d"),
    "Members" : [ 
        {
            "_id" : ObjectId("5e7dbf5b257e6b18a62f2da9"),
            "firstname" : "raed",
            "photo" : "/users/5e7dbf5b257e6b18a62f2da9/profile/profile-02b13aef6e.png"
        }, 
        {
            "_id" : ObjectId("5e7e2f048f80b46d786bfd67"),
            "firstname" : "sarra",
            "photo" : "/5e7e2f048f80b46d786bfd67/profile/profile-c79f91aa2e.png"
        }
    ]
}

错误:

$concat only supports strings, not array

【问题讨论】:

    标签: mongodb mongodb-query aggregation-framework


    【解决方案1】:

    您只需将pipeline 添加到$lookup 阶段即可

    db.events.aggregate([
      {
        $match: {
          _id: ObjectId("5e8b0bac041a913bc608d69d"),
        },
      },
      {
        $lookup: {
          from: "members",
          let: { memberId: "$members.memberId" },
          pipeline: [
            { $match: { $expr: { $in: ["$_id", "$$memberId"] } } },
            {
              $project: {
                firstname: 1,
                photo: { $concat: ["http://myurl", "$photo"] }
              }
            }
          ],
          as: "Members",
        }
      },
      /** Optional */
      {$project : {Members: 1}}
    ]);
    

    测试: MongoDB-Playground

    【讨论】:

      【解决方案2】:

      在上述答案中使用pipeline 的替代方法

      我们可以使用projectgroup

      db.events.aggregate([
          { 
              $match: { _id: ObjectId("5e8b0bac041a913bc608d69d") } 
          },
          {
              $unwind: '$members' // to spread the members array into a stream of documents
          },
          {
              $lookup: {
                  from: "members",
                  localField: "members.memberId",
                  foreignField: "_id",
                  as: "member"
              }
          },
          {
              $unwind: '$member' // each document will have array of only one member, so do this unwind to convert it to an object
          },
          {
              $project: { // do the project here to be able to use the $concat operator
                  'member._id': 1,
                  'member.firstname': 1,
                  'member.photo': 1,
                  'member.photo': { $concat: ['http://myurl', '$member.photo'] } // now we can use the $concat as member is an object, then member.photo exists
              }
          },
          {
              $group: { // do that grouping stage to gather all the members belong to the same document in one array again
                  _id: '$_id',
                  Members: {
                      $addToSet: '$member'
                  }
              }
          }
      
      ])
      

      【讨论】:

      • 我想提出一些建议 1) 两个$unwind 都很有可能丢失没有members 或@ 的文档987654327@(另外$unwind 具有爆炸性 - 所以除非需要,否则在大型数据集上不首选 - 查找时虽然内部机制可能相同也可能不同,但我会将其留给 MongoDB !!),2) 您可以只使用$push 而不是$addToSet - 这可能会减轻服务器的工作。 3) 这个$project 有两个字段反映相同的member.photo..
      猜你喜欢
      • 1970-01-01
      • 2020-07-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-05
      • 1970-01-01
      • 2023-01-04
      相关资源
      最近更新 更多