Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
405 views
in Technique[技术] by (71.8m points)

javascript - MongoDB Aggregate $lookup on array of object with additional field

I have two different collections (example below) methods & items. As for now, I'm using pre 3.6 vanilla aggregation query for $lookup:

MongoPlayground Example

  {
    $lookup: {
      from: "items",
      localField: "reagents._id",
      foreignField: "_id",
      as: "reagent_items"
    }
  }

The problem is that if I am using it, I miss quantity field (from methods.reagents embedded) during $lookup stage from original collection. For now, I return quantity right after lookup but as I heard, Mongo introduced from 3.6 a new syntax for lookup queries, so the question is:

Can it solve my problem for receiving the following results:

  {
    "_id": 1,
    "name": "Test",
    "reagent_items": [ // <= the exact schema of what I need after lookup
      {
        "_id": 1,
        "name": "ItemOne",
        "other": "field",
        "quantity": 2 //quantity field from original {array of objects} after lookup
      },
      {
        "_id": 2,
        "name": "ItemTwo",
        "other": "field",
        "quantity": 4 //quantity field from original {array of objects} after lookup
      }
    ],
    "reagents": [ //original reagents field here just for example, we could remove it
      {
        "_id": 1,
        "quantity": 2
      },
      {
        "_id": 2,
        "quantity": 4
      }
    ]
  }

methods

    {
      "_id": 1,
      "name": "Test",
      "reagents": [
        {
          _id: 1,
          quantity: 2
        },
        {
          _id: 2,
          quantity: 4
        }
      ]
    }

items

    {
      "_id": 1,
      "name": "ItemOne",
      "other": "field"
    },
    {
      "_id": 2,
      "name": "ItemTwo",
      "other": "field"
    }
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Use $map along with $arrayElemAt to find corresponding reagent for each reagent_items and the apply $mergeObjects to get one object:

db.methods.aggregate([
    {
        $lookup: {
            from: "items",
            localField: "reagents._id",
            foreignField: "_id",
            as: "reagent_items"
        }
    },
    {
        $project: {
            _id:1,
            name: 1,
            reagents: 1,
            reagent_items: {
                $map: {
                    input: "$reagent_items",
                    as: "ri",
                    in: {
                        $mergeObjects: [
                            "$$ri",
                            {
                                $arrayElemAt: [ { $filter: { input: "$reagents", cond: { $eq: [ "$$this._id", "$$ri._id" ] } } }, 0 ]
                            }
                        ]
                    }
                }
            }
        }
    }
])

Mongo Playground


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...