Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to query all subdocuments

I'm beginning with MongoDb and nodejs (using mongoose).

I have a collection of Stories, each of them can have one or more Tags, it's something like that:

{
    title: "The red fox",
    content: "The red fox jumps away...",
    tags: [
        {
            tagname: "fairytale",
            user: "pippo"
        },
        {
            tagname: "funny",
            user: "pluto"
        },
        {
            tagname: "fox",
            user: "paperino"
        }
    ]
},

... other stories

Now I want to make a tag cloud.

It means querying Stories for all tags.

In a relational world (e.g. MySQL) I would have a Stories table, a Tags table and a Stories_Tags table (many-to-many). Then I'd query on the tags table or something like that.

Is there a way to do so? (I'm sure yes)

If yes, is it a good practice? Or does it break the nosql paradigm?

Can you imagine a better way for my schema design?

like image 534
Fabio B. Avatar asked Aug 27 '12 09:08

Fabio B.


People also ask

How do I query an array of objects in MongoDB?

To search the array of object in MongoDB, you can use $elemMatch operator. This operator allows us to search for more than one component from an array object.

How do I search in MongoDB?

Find() Method. In MongoDB, find() method is used to select documents in a collection and return a cursor to the selected documents. Cursor means a pointer that points to a document, when we use find() method it returns a pointer on the selected documents and returns one by one.

What is MongoDB elemMatch?

Definition. $elemMatch. The $elemMatch operator matches documents that contain an array field with at least one element that matches all the specified query criteria.


1 Answers

Here is how you do this using the aggregation framework (you need to use just released 2.2).

db.stories.aggregate(
[
    {
        "$unwind" : "$tags"
    },
    {
        "$group" : {
            "_id" : "$tags.tagname",
            "total" : {
                "$sum" : 1
            }
        }
    },
    {
        "$sort" : {
            "total" : -1
        }
    }
])

Your result will look like this:

{
    "result" : [
        {
            "_id" : "fairytale",
            "total" : 3
        },
        {
            "_id" : "funny",
            "total" : 2
        },
        {
            "_id" : "silly",
            "total" : 1
        },
        {
            "_id" : "fox",
            "total" : 1
        }
    ],
    "ok" : 1
}
like image 119
Asya Kamsky Avatar answered Oct 12 '22 00:10

Asya Kamsky