MongoDB - matching multiple values ​​in an array

I want to be able to find multiple documents that have three or more matching values ​​in an array. Say we have the following documents:

[{ name: 'John', cars: [1, 2, 3, 4] }, { name: 'Jane', cars: [1, 2, 3, 8] }, { name: 'Smith', cars: [1, 8, 10] }] 

And we want to find documents that have at least three values ​​(in cars) in the following array:

  [1, 2, 3, 4, 5, 6, 7] 

Then the results will be as follows:

  [{ name: 'John', cars: [1, 2, 3, 4] }, { name: 'Jane', cars: [1, 2, 3, 8] }] 

Does anyone know how to achieve this?

+10
find mongodb
source share
3 answers

This is a good question, and I don't think there is an easy way to do this with the usual operators that MongoDB gives you. However, I can come up with the following ways to do this:

1. New field

Calculate this in the application code and save the result in a new document field.

2. Brute force

 db.Collection.find( { $or: [ { cars: $all [ 1, 2, 3 ] }, { cars: $all [ 2, 3, 4 ] }, ... list out all 35 combinations ] } ) 

3. Use $where

 db.Collection.find( { cars: { $in: [1,2,3,4,5,6,7] }, $where: function() { var numMatches = 0; for (var i = 1; i <= 7; i++) if (this.cars.indexOf(i) > -1) numMatches++; return numMatches >= 3; } } ); 
+8
source share

You can get a $in request, and then filter by the code the record containing 3 or more records in the desired array. (Here are some simple python code)

 def dennisQuestion(): permissibleCars = [1,2,3,4,5,6,7] cursor = db.collection.find({"cars": {"$in": permissibleCars}}) for record in cursor: if len(set(permissible) & set(record["cars"]))) >= 3 yield record 
+13
source share

I had to slightly modify @Zaid Masud option 3 when the values ​​are where the lines are in Mongo 4.0.3:

 db.Collection.find( { cars: { $in: ["s1", "s2", "s3" , "s4", "s5" , "s6" , "s7"] }, $where: function() { var options = ["s1", "s2", "s3" , "s4", "s5" , "s6" , "s7"]; var numMatches = 0; for (var i = 0; i < 7; i++) if (this.cars.indexOf(options[i]) > -1) numMatches++; return numMatches >= 3; } } ); 

(It seemed a bit big for comment)

0
source share

All Articles