У меня есть 2 Монго коллекции:MongoDB запросов объединения двух коллекций
компании: Каждая запись является компанией с большим количеством полей (город, страна, и т.д.) ->100k rows
{company_id:1, country:"USA", city:"New York",...}
{company_id:2, country:"Spain", city:"Valencia",... }
{company_id:3, country:"France", city:"Paris",... }
оценки : Имеются блоки дат, и каждый блок имеет оценку company_id +, пример ->100k rows in each block
{date: 2016-05-29, company_id:1, score:90}
{date: 2016-05-29, company_id:2, score:87}
{date: 2016-05-29, company_id:3, score:75}
...
{date: 2016-05-22, company_id:1, score:88}
{date: 2016-05-22, company_id:2, score:87}
{date: 2016-05-22, company_id:3, score:76}
...
{date: 2016-05-15, company_id:1, score:91}
{date: 2016-05-15, company_id:2, score:82}
{date: 2016-05-15, company_id:3, score:73}
...
Цель:
Я хочу, чтобы получить список компаний, которые могут быть отфильтрованы по некоторым полям (страна, город, ...) + свой новый счет (в 2016-05-29), ordered by score descending
То есть: фильтр в сборе, один фильтре + порядка в другой коллекции
Примечание: Там есть индекс scores.date
, и мы можем найти/заранее рассчитать легко и быстро самую высокую дату (2016-05-29 в этот пример)
Попытки:
Я пробовал запрос aggregate
с использованием $lookup
. Когда фильтр завершен (и количество малых компаний), запрос выполняется быстрее.
запроса, как показано ниже: -
db.companies.aggregate([
{$match: {"status": "running", "country": "USA", "city": "San Francisco",
"categories": { $in: ["Software"]}, dummy: false}},
{$lookup: {from: "scores", localField: "company_id", foreignField: "company_id", as:"scores"}},
{$unwind: "$scores"},
{$project: {_id: "$_id",
"company_id": "$company_id",
"company_name": "$company_name",
"status": "$status",
"city": "$city",
"country": "$country",
"categories": "$categories",
"dummy": "$dummy",
"score": "$scores.score",
"date": "$scores.date"}},
{$match: {"date" : ISODate("2016-05-29T00:00:00Z")}},
{$sort: {"score":-1}}
],{allowDiskUse: true})
Но когда фильтр мал или пустой (больше компаний), то $sort
часть занимает несколько секунд.
db.companies.aggregate([
{$match: {"status": "running"}},
{$lookup: {from: "scores", localField: "company_id", foreignField: "company_id", as:"scores"}},
{$unwind: "$scores"},
{$project: {_id: "$_id",
"company_id": "$company_id",
"company_name": "$company_name",
"status": "$status",
"city": "$city",
"country": "$country",
"categories": "$categories",
"dummy": "$dummy",
"score": "$scores.score",
"date": "$scores.date"}},
{$match: {"date" : ISODate("2016-05-29T00:00:00Z")}},
{$sort: {"score":-1}}
],{allowDiskUse: true})
Наверное, потому, что количество компаний, найденных фильтром. 59 строк проще заказать, чем 89K
> db.companies.count({"status": "running", "country": "USA", "city": "San Francisco", "categories": { $in: ["Software"]}, dummy: false})
59
> db.companies.count({"status": "running"})
89043
Я попробовал другой подход, агрегирование по баллам, фильтр по дате, сортировка по баллам (дата индекса + оценка очень полезно здесь), и все очень быстро, до последнего $match
когда фильтр компании атрибуты
db.scores.aggregate([
{$match:{"date" : ISODate("2016-05-29T00:00:00Z")}},
{$sort:{"score":-1}},
{$lookup:{from: "companies", localField: "company_id", foreignField: "company_id", as:"companies"}},
{$unwind:"$companies"},
{$project: {_id: "$companies._id",
"company_id": "$companies.company_id",
"company_name": "$companies.company_name",
"status": "$companies.status",
"city": "$companies.city",
"country": "$companies.country",
"categories": "$companies.categories",
"dummy": "$companies.dummy"}},
"score": "$score",
"date": "$date"
{$match:{"status": "running", "country":"USA", "city": "San Francisco",
"categories": { $in: ["Software"]}, dummy: false}}
],{allowDiskUse: true})
, используя этот подход, большой фильтр (предыдущий пример) очень медленно, а маленький фильтр (только {"status": "running"}
) быстрее
Любой путь объединить оба ections, фильтр в обоих из них и порядок по одному полю?
Дело для присоединений https://www.mongodb.com/blog/post/joins-and-other-aggregation-enhancements-coming-in-mongodb-3-2-part-1-of-3-introduction – Leo