Я выполняю некоторую статистическую команду с $ lookup и хочу выбрать только один документ из результата поиска на основе некоторого значения.
Пример:
// Add some users
db.users.insert([
{_id: "1", name: "john"},
{_id: "2", name: "jack"},
{_id: "3", name: "jenny"}
])
// Users have projects (owner field refers to user _id)
db.projects.insert([
// Johns projects
{owner: "1", name: "john1", lastUpdate: ISODate("2018-01-01T11:00:00")},
{owner: "1", name: "john2", lastUpdate: ISODate("2018-01-01T12:00:00")},
// Jennys projects
{owner: "3", name: "jenny1", lastUpdate: ISODate("2018-01-01T11:00:00")},
{owner: "3", name: "jenny2", lastUpdate: ISODate("2018-01-01T13:00:00")},
{owner: "3", name: "jenny3", lastUpdate: ISODate("2018-01-01T12:00:00")}
])
Теперь я хочузапустить агрегат на users
и добавить проект с самым последним значением lastUpdate
.Я нашел 2 способа сделать это и удивился, как узнать, что лучше (с точки зрения производительности), и есть ли третий, более простой и / или эффективный.
(Примечание: цель сводного запроса -не только для получения последнего проекта, это всего лишь один шаг в более сложном запросе) (Примечание 2: MongoDB 3.6)
Спасибо!
Первый вариант
db.users.aggregate([
{$lookup: {from: 'projects', localField: '_id', foreignField: 'owner', as: 'projects'}},
{$addFields: {
latest_project: {
$arrayElemAt: [
{
$filter: {
input: '$projects',
as: 'proj',
cond: { $eq: [ '$$proj.lastUpdate', { $max: '$projects.lastUpdate' } ] }
}
}, 0
]
}
}}
])
Второй вариант
db.users.aggregate([
{$lookup: {
from: 'projects',
let: {uid: '$_id'},
pipeline: [
{$match: {$expr: {$eq: [ "$owner", "$$uid" ]}}},
{$sort: {lastUpdate: -1}},
{$limit: 1}
],
as: 'projects'
}},
{$addFields: {project: {$arrayElemAt: ['$projects', 0]}}}
])