MongoDB - сопоставление нескольких значений в массиве
Я хочу, чтобы иметь возможность найти несколько документов, которые имеют три или более совпадающих значений в массиве. Скажем, мы имеем следующие документы:
[{
name: 'John',
cars: [1, 2, 3, 4]
},
{
name: 'Jane',
cars: [1, 2, 3, 8]
},
{
name: 'Smith',
cars: [1, 8, 10]
}]
И мы хотим найти документы, имеющие по крайней мере три значения (в автомобилях) в следующем массиве:
[1, 2, 3, 4, 5, 6, 7]
Тогда результаты будут следующими:
[{
name: 'John',
cars: [1, 2, 3, 4]
},
{
name: 'Jane',
cars: [1, 2, 3, 8]
}]
Кто-нибудь знает, как достичь этого?
Ответы
Ответ 1
Это хороший вопрос, и я не думаю, что есть простой способ сделать это с обычными операторами, которые дает вам MongoDB. Однако я могу придумать следующие способы для этого:
1. Новое поле
Рассчитайте это в коде приложения и сохраните результат в новом поле документа.
2. Грубая сила
db.Collection.find( { $or: [
{ cars: $all [ 1, 2, 3 ] },
{ cars: $all [ 2, 3, 4 ] },
... list out all 35 combinations
] } )
3. Используйте $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;
} } );
Ответ 2
Вы можете получить запрос $in
, а затем по коду фильтровать запись, содержащую 3 или более записей в нужном массиве. (Вот несколько простых python-кода)
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
Ответ 3
Мне пришлось немного изменить @Zaid Masud вариант 3, когда значения, где строки в 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;
}
} );
(Это казалось немного большим для комментария)