Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MongoDB - Filtering the content of an internal Array in a resultset

Tags:

mongodb

filter

I'm new using MongoDB, and I don't know how to solve the next problem:

I have a collection of documents like this:

{
 "URL": "www.stackoverflow.com",
 "TAGS": [
         {"NAME": "question", "VOTES": 3},
         {"NAME": "answer", "VOTES": 5},
         {"NAME": "problem", "VOTES": 2}
         ]
}

First of all, I wanted all the Urls that have all the tags given in a list. I have solved this by quering:

db.links.find( { "Tags.Name" : { $all: ["question","answers"] } } );

But this query return the whole correct document, insted of only the correct document with only the tags I have asked for.

The result I'm looking for is:

{
 "URL": "www.stackoverflow.com",
 "TAGS": [{"NAME": "question", "VOTES": 3},
         {"NAME": "answer", "VOTES": 5}]
}

and not:

{
 "URL": "www.stackoverflow.com",
 "TAGS": [{"NAME": "question", "VOTES": 3},
         {"NAME": "answer", "VOTES": 5},
         {"NAME": "problem", "VOTES": 2}]
}

Because I've only asked for the tags ["question","answers"].

I thought about using MapReduce or parsing the resultset, but I don't know if it is the correct way of solving the problem. Maybe there is a builtin function that solve it more efficiently.

Thanks!

like image 227
Martin Zugnoni Avatar asked Jan 15 '11 18:01

Martin Zugnoni


People also ask

How do I filter an array in MongoDB?

Filter MongoDB Array Element Using $Filter Operator This operator uses three variables: input – This represents the array that we want to extract. cond – This represents the set of conditions that must be met. as – This optional field contains a name for the variable that represent each element of the input array.

How do I remove an element from an array in MongoDB?

To remove an element, update, and use $pull in MongoDB. The $pull operator removes from an existing array all instances of a value or values that match a specified condition.

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.


1 Answers

I was just referenced to this conversation from a link to my own solution to the problem. It does work, but in hindsight the real issue was that I didn't understand MongoDB back then.

My conclusion: if you find yourself filtering embedded arrays in MongoDB, it probably means you don't understand MongoDB.

The official solution to this issue

The official recommendation is to prefer embedding data over referencing or filtering it.

Yes, this means you're expected to duplicate data. Yes, this means you're making your DB less abstract and more tailored to your specific solution.

And yes, this might feel strange coming from SQL.

Meaning...

My suggestion would be to create a new collection for the answers, and embed the correct ones into the URL entity. It's called "the embedded subset pattern".

The technical, wrong, solution

Back then before MongoDB clicked for me, I managed to filter internal arrays, server side, by overriding the property storing the array with a filtered subset of it.

You can read about it here. Again - even though I'm really fond of my hack, I do not recommend it. It's basically a monument to how much I didn't understand MongoDB back then.

like image 98
Vaiden Avatar answered Sep 20 '22 17:09

Vaiden