8

I am using Mongoose in a MEAN environment. How can I make sure to not have any duplicate results in my result set? Example: my database contains 10 (partly duplicate) names:

  • Allan
  • Allan Fourier
  • Allan
  • Allan Maxwell
  • Allan
  • Allan Foo
  • Allan Whatever
  • Allan Whoever
  • Allan Smith
  • Allan Rogers

When querying this database for 'Allan' or maybe even just 'all' (using .find(regex...) and limiting the number of returned results to 5, I get this:

  • Allan
  • Allan Fourier
  • Allan
  • Allan Maxwell
  • Allan

Having three duplicate entries of 'Allan', we waste a lot of result-diversity (talking about an autocomplete function for a search input field). I need the returned result set free of duplicates, such as:

  • Allan
  • Allan Fourier
  • Allan Maxwell
  • Allan Foo
  • Allan Whatever

How can that be achieved using mongoose, if at all?

2
  • You want to control inserting duplicate values or duplicate search result? Commented May 4, 2015 at 0:33
  • I want to control duplicate search result (= no duplicate elements inside of the returned result) Commented May 4, 2015 at 0:38

3 Answers 3

13

You can use find to establish the query and then chain a call to distinct on the resulting query object to get the unique names in the result:

var search = 'Allan'; Name.find({name: new RegExp(search)}).distinct('name').exec(function(err, names) {...}); 

Or you can combine it all into a call to distinct on the model, providing the query object as the second parameter:

var search = 'Allan'; Name.distinct('name', {name: new RegExp(search)}, function(err, names) {...}); 

In both cases, names is an array of just the distinct names, not full document objects.

You can also do this with aggregate which would then let you directly limit the number of results:

Name.aggregate([ {$match: {name: new RegExp(search)}}, {$group: {_id: '$name'}}, {$limit: 5} ]) 
Sign up to request clarification or add additional context in comments.

5 Comments

Thanks for that but is there also a way to limit the amount of results as I can't use distinct() and .limit together :(
@IgorP. Not directly. But you can easily take just the first N elements from the array of names. e.g. names.slice(0, 5).
I see. Still, I'd like to avoid querying the entire database for every request for performance reasons. Too bad there is no native way to combine .distinct() and limit. Any other suggestions how to get a limited amount of dinstinct results for a regex search?
@IgorP. You can also use aggregate to do this which does let you limit the results. See the updated answer.
How would you get the object, not just the value of the field? I want to do a .find() and only return the ones if the value for a field is different then the other ones in the others. like if I have a name field and some docs have the same name, I want to only return the doc 1 for the name. and the same for all other docs with different name values
0

You can use MongoDB's distinct() query to find only distinct values (i.e., unique) in your set. Per the API docs, distinct can be used with Mongoose.

Their example:

{ "_id": 1, "dept": "A", "item": { "sku": "111", "color": "red" }, "sizes": [ "S", "M" ] } { "_id": 2, "dept": "A", "item": { "sku": "111", "color": "blue" }, "sizes": [ "M", "L" ] } { "_id": 3, "dept": "B", "item": { "sku": "222", "color": "blue" }, "sizes": "S" } { "_id": 4, "dept": "A", "item": { "sku": "333", "color": "black" }, "sizes": [ "S" ] } 

With db.inventory.distinct( "dept" ) will return [ "A", "B" ]

5 Comments

But distinct() is "native MongoDB", thus skipping Mongoose (which I don't want to) or can I combine that somehow?
Look at the Mongoose docs that I linked, they provided access to the base distinct method. You can find it here: mongoosejs.com/docs/api.html#query_Query-distinct
I see, but that still does not work with regular expressions inside (which I use), right? 'Name.find().distinct({name: new RegExp()});' gives me a TypeError
You can feel free to post your code, but it doesn't seem you are using Mongoose right. If you want to match a RegExp, you should be using the $regex method.
Oh ok. This is my query: var searchQuery = Name.find().distinct({name: new RegExp("...")}); Wrong?
0

You can filter the search result which is array using method suggested here:

Delete duplicate from Array

1 Comment

Sorry, but that's not what I am looking for. If possible I'd like to always return 5 (unique) results. If I query the database for 5 results and then filter the result set manually - using your approach - then I end up with only 3 results (sticking to my example). The filtering must therefore be initiated natively on the database layer.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.