11

I have a collection in mongodb where fields are nested under a language root:

{
    en: {
        title: "eng title",
        content: "eng content",
    },
    it: {
        title: "it title",
        content: "it content"
    }
    //common attributes for all languages
    images: {
        mainImage: "dataURL",
        thumbImage: "dataURL"
    }
}

I have a variable called 'currentLang'; I need to find a document by title selecting only the "currentLang" object and the common fields (images in this example); but for the "currentLang" object, I would like to have the output document not nested; for example, having currentLang = "en"

desired output:

{
    title: "eng title",
    content: "eng content",
    images: {
        mainImage: "dataURL",
        thumbImage: "dataURL"
    }
}

Is this possible?

2 Answers 2

7

You need to aggregate as below:

  • Construct a find object to match only the records containing($exists) the language.
  • Construct a Projection object to project the fields.

Code:

var currentLang = "en";
var project = {};
project["title"] = "$"+currentLang+".title";
project["content"] = "$"+currentLang+".content";
project["images"] = 1;

var find = {};
find[currentLang] = {"$exists":true};

db.collection.aggregate([
{$match:find},
{$project:project}
])
Sign up to request clarification or add additional context in comments.

5 Comments

This is exactly the code that I'm using now; but the output document is still nested under "en"; I would like to have all fields in the root element, like the desired output written above
@CerealKiller Then you need to aggregate, to project a field with an alias. Please see the updated answer.
Ok, this is correct; unfortunally, I'm using mongo inside Meteor.js, where aggregation seems to be not supported; sorry when I wrote the question I was not knowing that...
@CerealKiller No problem. - See if this helps stackoverflow.com/questions/18520567/…. Or You can post a new question asking for how this is to be done using meteor.
Not super significant, but to follow standards -- Since the top 3 obj keys are static and known, you may want to use project.title = instead of project["title"] = (you can use the dot notation to create NEW fields inside the obj on-the-fly - it's ok if undefined as long as it's not nested undefined)
4

I'm not sure how you're querying, so I'll assume you're going directly through the mongo client. Assuming you have defined a variable

>currentLang = "en";

You can run an aggregation operation and using the $project operator, restructure the presentation of the document.

Here's an example that I've tested:

> db.test.aggregate({$project: 
        {_id: 0, 
         title: "$" + currentLang + ".title", 
         content: "$" + currentLang + ".content", 
         images: 1
        }
    }).pretty();
{
    "images" : {
        "mainImage" : "dataURL",
        "thumbImage" : "dataURL"
    },
    "title" : "eng title",
    "content" : "eng content"
}

If you want to combine this with an actual query, you can just include it as a $match operator, something like:

> db.test.aggregate(
    {$match: 
        {"en.title": "eng title"}
    }, 
    {$project: 
        {_id: 0, 
         title: "$" + currentLang + ".title", 
         content: "$" + currentLang + ".content", 
         images: 1
        }
    }).pretty();

Comments

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.