Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MongoDB: find documents that match the most tags

Tags:

mongodb

meteor

In my meteor app, I have a huge collection of documents, each with a field tags, basically like this:

{..., tags: ["a","b","c"], ...},
{..., tags: ["a","b","d"], ...},
{..., tags: ["b","c","e"], ...},
{..., tags: ["x","y","z"], ...},
....

Now i want to query the collection on the server with some tags, eg: ["a","d","y"] and get all results that match at least one tag, and the resultset sorted by the number of matching tags. So, in the exampleset the result should be:

{..., tags: ["a","b","d"], ...},
{..., tags: ["a","b","c"], ...},
{..., tags: ["x","y","z"], ...}

because the first doc has two matches, "a" and "d", and the other two elements have one match, "a" and "y".

Currently I know that I can use $in to match all documents that have at least one match, $all to get all documents where every tag matches, but this doesn't cut it somehow. I could also use mongoDB's aggregate framework if needed.

What would the needed query look like?

like image 917
Maximilian Stroh Avatar asked Dec 06 '14 00:12

Maximilian Stroh


People also ask

How to find matching documents given an array with values in MongoDB?

MongoDB query to find matching documents given an array with values? For specific documents, use MongoDB $ in. Let us create a collection with documents − Display all documents from a collection with the help of find () method −

How to find a document from MongoDB collection?

Find method is used to fetch a document from the MongoDB collection. Using the Find method, we can fetch specific documents as well as the particular fields that we need. We can also use other find methods to retrieve specific documents as per our requirement.

How many methods available in MongoDB to fetch particular records?

There are totally six methods available in Mongo DB by which we can fetch particular records. Find method consists of two parameters by which we can fetch a particular record. If we don’t use these two parameters then the find method will return all the documents available within the MongoDB collection.

What happens if we don’t use the find method in MongoDB?

If we don’t use these two parameters then the find method will return all the documents available within the MongoDB collection. Query – This is an optional parameter which defines the selection criteria.


1 Answers

I could also use mongoDB's aggregate framework if needed.

You need to use the the aggregation pipeline, which can be written as below:

  • Match the documents having at least one matching value in the tags array.
  • We will be unwinding and working on the tags array, so keep a copy of the tags array in each record.
  • Unwind the tags array.
  • Match the records which have their tags value present in the input array.
  • Group by the _id field and calculate the number of documents that have matched.
  • Sort the groups based on their number of matches.
  • project the required fields along with the original tags array copy we had created.

Code:

var inp = ["a","d","y"];

db.collection.aggregate([
{$match:{"tags":{$in:inp}}},
{$project:{"tagsCopy":"$tags","tags":1}},
{$unwind:"$tags"},
{$match:{tags:{$in:inp}}},
{$group:{"_id":"$_id","noOfMatches":{$sum:1},"tags":{$first:"$tagsCopy"}}},
{$sort:{noOfMatches:-1}},
{$project:{"_id":0,"noOfMatches":1,tags:1}} //remove noOfMatches and 
                                            //add other required 
                                            //fields which are necessary.
])

o/p:

{ "noOfMatches" : 2, "tags" : [ "a", "b", "d" ] }
{ "noOfMatches" : 1, "tags" : [ "x", "y", "z" ] }
{ "noOfMatches" : 1, "tags" : [ "a", "b", "c" ] }
like image 194
BatScream Avatar answered Nov 15 '22 05:11

BatScream