S.C.
S.C.

Reputation: 2874

Mongo db grouping + distinct

Given a mongodb collection like this:

c = [{
    "name": "john",
    "tags": ["a", "b", "c"],
    "values": [1, 2, 3]
  },
  {
    "name": "paul",
    "tags": ["a", "d"],
    "values": [3, 4, 5]
  }
]

I'd like to make a query that matches some criteria and then return a distinct copy of all criteria available from the retrieved document, so that if i query for:

"all documents whose tags includes value a"

I'd get:

[
  {
     "name": "john"
  },
  {
     "name": "paul"
  },
  "aggregated_tags": ["a", "b", "c", "d"],
  "aggregated_values": [1, 2, 3, 4, 5]
]

I already came to a solution, but I'm not happy with it, since it involves list processing in Python to make sure I filter out all duplicated terms I got in the "available_tags" and "available_values", so I'm looking for an aggregation command that does the job.

I'm aware I should make use of some sort of mongo aggregation, but even though I'm able to make query with correct criteria, I still cannot figure out how to aggregate/distinct the criteria fields I get as results.

Upvotes: 0

Views: 144

Answers (1)

Neil Lunn
Neil Lunn

Reputation: 151072

The end result structure you are looking for wouldn't make much sense in terms of a returned collection, but a I presume you are actually pointing to some pseudo structure or other data structure for code that you want.

After unwinding in aggregation you can use $addToSet to get the distinct values. Example follows with just tags for brevity, but just to get the gist:

db.tags.aggregate([
    {$project: { _id: 0, tags: 1 }},
    {$unwind: "$tags" },
    {$sort: { tags: -1 } },
    {$group:{ _id: null, tags: {$addToSet: "$tags"} }},
}])

Sorting is optional to maintain order if that is important.

Of course you need a traditional query to return the document contents for elements matching, but a separate aggregation query can give you the combined tags and values from that set of documents, which appears to be what you are after.

This is especially useful if your matching documents is a large result and you just want to display say 20 of the matches only, but still want the combined tags from all of the matching documents.

On that note, if what you are after is some kind of faceted search result, then there may be some reading that you find useful to your goal.

http://blog.mongodb.org/post/59757486344/faceted-search-with-mongodb

Upvotes: 1

Related Questions