1

Assuming the following a portfolio collection:

{
    "_id" : ObjectId("50e5a858ad06fe3439000001"),
    "name" : "Portfolio 1",
    "description" : "description Portfolio 1",
    "userId" : "",
    "wallets" : [ ]
}
{
    "_id" : ObjectId("50e5a858ad06fe3439000002"),
    "name" : "Portfolio 2",
    "description" : "description Portfolio 2",
    "userId" : "",
    "wallets" : [
        {
            "_id" : ObjectId("50e5ac69f214a46139000001"),
            "name" : "wallet name 2-1",
            "description" : "description du wallet",
        "cards" : [
            {
                "_id" : ObjectId("50ebe4b5906a1e830d000001"),
                "name" : "Card 2-1-1",
                "description" : "description card 1",
            },
            {
                "_id" : ObjectId("50ebe61f2c0f189310000001"),
                "name" : "Card 2-1-2",
                "description" : "description de la carte",
            },
            {
                "_id" : ObjectId("50ebe6202c0f189310000002"),
                "name" : "Card 2-1-2",
                "description" : "description de la carte",
            },
            {
                "_id" : ObjectId("50ebe6212c0f189310000003"),
                "name" : "Card 2-1-3",
                "description" : "description de la carte",
            },
            {
                "_id" : ObjectId("50ebe6212c0f189310000004"),
                "name" : "Card 2-1-4",
                "description" : "description de la carte",
            }
        ]
    },
    {
        "_id" : ObjectId("50ebe6b22c0f189310000005"),
        "name" : "wallet 2-2",
        "description" : "",
        "cards" : [
            {
                "_id" : ObjectId("50ec21063f3c5f9f12000001"),
                "name" : "Card 2-2-1",
                "description" : "",
            }
        ]
    },
    {
        "_id" : ObjectId("50ebe6ba2c0f189310000006"),
        "name" : "wallet 2-3",
        "description" : "",
        "cards" : [
            {
                "_id" : ObjectId("50ec21233f3c5f9f12000002"),
                "name" : "Card 2-3-1",
                "description" : "",
            }
        ]
    }
]
}

I would like to access a specific card thanks to portfolio,wallet and card _id. What I'd like to have is:

{
"_id" : ObjectId("50e5a858ad06fe3439000002"),
"wallets" : [
    {
        "_id" : ObjectId("50e5ac69f214a46139000001"),
        "cards" : [
            {
                "_id" : ObjectId("50ebe4b5906a1e830d000001"),
                "name" : "Card 2-1-1",
                "description" : "description card 1",
            }
        ]
    },
]

}

I'm working on mongodb 2.2.2 on nodejs/mongo-native-driver.

Any help will be appreciate (shell example or javascript appreciated)

Thanck you.

3 Answers 3

3

Similar to slee's answer using the Aggregation Framework, though it's better to cull entries out of the results early to prevent unnecessary unwinding.

    var aggOps = [
        { $match: {
            _id: portfolioID
        }},
        {$unwind: '$wallets'},
        { $match: {
            'wallets._id': walletID
        }},
        {$unwind: '$wallets.cards'},
        { $match: {
            'wallets.cards._id': cardID
        }},
    ];

    collection.aggregate(aggOps, function (err, result) {
        console.log(result);
    });
Sign up to request clarification or add additional context in comments.

1 Comment

Yup, mjhm's right. It's definitely better to put $match earlier in the pipeline to reduce the number of documents being operated upon later in the pipeline.
1

The Aggregation Framework can be used. Specifically, the $unwind operator is probably most useful in this case. Bear in mind that $unwind won't expand empty arrays, so the first document in your example is excluded from the aggregation pipeline.

db.collection.aggregate(
    { $unwind : "$wallets" },
    { $unwind : "$wallets.cards" },
    { $match: {
        "_id"               : ObjectId("50e5a858ad06fe3439000002"),
        "wallets._id"       : ObjectId("50e5ac69f214a46139000001"),
        "wallets.cards._id" : ObjectId("50ebe4b5906a1e830d000001")
    } }
)

Comments

1

http://docs.mongodb.org/manual/reference/projection/elemMatch/

According to the mongodb documents this can be done by $elemMatch operator. I tried to come up with the query, can you check if it works for your case or you can modify according to your needs.

var projection = { _id: 1, wallets: { _id: 'walletId', $elemMatch: { cards._id: 'cardId'}}};

db.portfolio.find(    {_id: 'portfolio_id'},    projection )

2 Comments

$elemMatch works for projecting the correct wallet item, but it doesn't seem to work for the nested cards array.
Can you try: db.portfolio.find( {_id: 'portfolio_id', "wallets._id" : 'walletId'}, projection ). Not sure of exact syntax for the query.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.