How can I retrieve relative document in MongoDB?

Question:

I’m using Flask with Jinja2 template engine and MongoDB via pymongo. This are my documents from two collections (phone and factory):

phone = db.get_collection("phone")

{
    "_id": ObjectId("63d8d39206c9f93e68d27206"),
    "brand": "Apple",
    "model": "iPhone XR",
    "year": NumberInt("2016"),
    "image": "https://apple-mania.com.ua/media/catalog/product/cache/e026f651b05122a6916299262b60c47d/a/p/apple-iphone-xr-yellow_1.png",
    "CPU": {
        "manufacturer": "A12 Bionic",
        "cores": NumberInt("10")
    },
    "misc": [
        "Bluetooth 5.0",
        "NFC",
        "GPS"
    ],
    "factory_id": ObjectId("63d8d42b7a4d7a7e825ef956")
}

factory = db.get_collection("factory")
{
    "_id": ObjectId("63d8d42b7a4d7a7e825ef956"),
    "name": "Foxconn",
    "stock": NumberInt("1000")
}

In my python code to retrieve the data I do:

models = list(
    phone.find({"brand": brand}, projection={"model": True, "image": True, "factory_id": True})
)

How can I retrieve relative factory document by factory_id and have it as an embedded document in a models list?

Asked By: Vitalii Mytenko

||

Answers:

I think you are looking for this query using aggregation stage $lookup.

So this query:

  • First $match by your desired brand.
  • Then do a "join" between collections based on the factory_id and store it in an array called "factory". The $lookup output is always an array because can be more than one match.
  • Last project only values you want. In this case, as _id is unique you can get the factory using $arrayElemAt position 0.

So the code can be like this (I’m not a python expert)

models = list(
    phone.aggregate([
        {
            "$match": {
                "brand": brand
            }
        },
        {
            "$lookup": {
                "from": "factory",
                "localField": "factory_id",
                "foreignField": "_id",
                "as": "factories"
            }
        },
        {
            "$project": {
                "model": True,
                "image": True,
                "factory": {
                    "$arrayElemAt": [
                        "$factories",
                        0
                    ]
                }
            }
        }
    ])
)
Answered By: J.F.
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.