MongoDB 查找管道中的数组匹配
Array match in MongoDB lookup pipeline
我有两个 collection。一件艺术品,另一件 collections(多件艺术品的专辑)。
每个作品都有一个“collections”字段,该字段是一个数组,其中保存了它所属的collections的id。
我想做的是获取用户的所有 collection 以及每个 collection 的前 4 幅作品(以在应用程序中显示预览)。
然而,这个本来以为很简单的东西,原来更复杂。
在正常查询中我会这样做:
artworkModel.find({
collections: collection
})
但是,在聚合管道中,这不起作用,所以我实施的解决方案是:
[
{$match: {
author: author,
},
},
{
$lookup: {
from: 'artworks',
as: 'previews',
let: { collection: '$_id' },
pipeline: [
{
$match: {
collections: { $exists: true },
$expr: { $in: ['$$collection', '$collections'] },
},
},
{ $sort: { date: -1 } },
{ $limit: 4 },
{ $addFields: { id: '$_id' } },
],
},
}
]
问题是我不能接受这个解决方案,因为与上面的查询不同,它不使用“collections”字段上的索引,因此对 collection.感谢帮助。
编辑:示例数据
作品:
[
{
"_id": { "$oid": "612fa9541121d06014e7d9bc" },
"collections": [
{ "$oid": "612fa9481121d06014e7d9b5" },
{ "$oid": "612fa9f6b2cc520a84e83dde" }
],
"author": { "$oid": "5fe8fe53ff8d9dc25c9e3277" },
"text": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam vestibulum dolor id justo condimentum ",
"type": "Text"
},
{
"_id": { "$oid": "60eec90e787a0b320c514446" },
"author": { "$oid": "5fe8fe53ff8d9dc25c9e3277" },
"type": "Image",
"asset": { "$oid": "60eec90e787a0b320c514441" },
"collections": [{ "$oid": "612fa9f6b2cc520a84e83dde" }]
},
{
"_id": { "$oid": "612fa9f2b2cc520a84e83db1" },
"collections": [{ "$oid": "612fa9f6b2cc520a84e83dde" }],
"author": { "$oid": "5fe8fe53ff8d9dc25c9e3277" },
"text": "Lorem ipsum dolor sit amet",
"type": "Text"
},
{
"_id": { "$oid": "612549d4778270001862472f" },
"author": { "$oid": "5fe8fe53ff8d9dc25c9e3277" },
"type": "Video",
"asset": { "$oid": "612549d4778270001862472a" }
}
]
collections:
[
{
"_id": { "$oid": "612fa9f6b2cc520a84e83dde" },
"name": "Name",
"author": { "$oid": "5fe8fe53ff8d9dc25c9e3277" },
"itemsCount": 3,
}
]
我认为以下查询与您的查询相同。
在 运行 之前,它在 artworks.collections
上创建索引(多键索引)
查询
- 根据作者过滤集合
- 使用索引加入正常查找
- 与 1 个集合进行虚拟连接
[{}]
仅用于应用管道
你想要的,就像一个把戏
如果可以的话请测试一下,然后告诉我它是否有效以及速度是否足够快
db.collections.aggregate([
{
"$match": {
"author": {
"$eq": "5fe8fe53ff8d9dc25c9e3277"
}
}
},
{
"$lookup": {
"from": "artworks",
"localField": "_id",
"foreignField": "collections",
"as": "previews"
}
},
{
"$lookup": {
"from": "dummy",
"let": {
"previews": "$previews"
},
"pipeline": [
{
"$set": {
"previews": "$$previews"
}
},
{
"$unwind": {
"path": "$previews"
}
},
{
"$replaceRoot": {
"newRoot": "$previews"
}
},
{
"$sort": {
"date": -1
}
},
{
"$limit": 4
},
{
"$set": {
"id": "$_id"
}
},
{
"$unset": [
"_id"
]
}
],
"as": "previews"
}
}
])
我有两个 collection。一件艺术品,另一件 collections(多件艺术品的专辑)。 每个作品都有一个“collections”字段,该字段是一个数组,其中保存了它所属的collections的id。
我想做的是获取用户的所有 collection 以及每个 collection 的前 4 幅作品(以在应用程序中显示预览)。
然而,这个本来以为很简单的东西,原来更复杂。
在正常查询中我会这样做:
artworkModel.find({
collections: collection
})
但是,在聚合管道中,这不起作用,所以我实施的解决方案是:
[
{$match: {
author: author,
},
},
{
$lookup: {
from: 'artworks',
as: 'previews',
let: { collection: '$_id' },
pipeline: [
{
$match: {
collections: { $exists: true },
$expr: { $in: ['$$collection', '$collections'] },
},
},
{ $sort: { date: -1 } },
{ $limit: 4 },
{ $addFields: { id: '$_id' } },
],
},
}
]
问题是我不能接受这个解决方案,因为与上面的查询不同,它不使用“collections”字段上的索引,因此对 collection.感谢帮助。
编辑:示例数据
作品:
[
{
"_id": { "$oid": "612fa9541121d06014e7d9bc" },
"collections": [
{ "$oid": "612fa9481121d06014e7d9b5" },
{ "$oid": "612fa9f6b2cc520a84e83dde" }
],
"author": { "$oid": "5fe8fe53ff8d9dc25c9e3277" },
"text": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam vestibulum dolor id justo condimentum ",
"type": "Text"
},
{
"_id": { "$oid": "60eec90e787a0b320c514446" },
"author": { "$oid": "5fe8fe53ff8d9dc25c9e3277" },
"type": "Image",
"asset": { "$oid": "60eec90e787a0b320c514441" },
"collections": [{ "$oid": "612fa9f6b2cc520a84e83dde" }]
},
{
"_id": { "$oid": "612fa9f2b2cc520a84e83db1" },
"collections": [{ "$oid": "612fa9f6b2cc520a84e83dde" }],
"author": { "$oid": "5fe8fe53ff8d9dc25c9e3277" },
"text": "Lorem ipsum dolor sit amet",
"type": "Text"
},
{
"_id": { "$oid": "612549d4778270001862472f" },
"author": { "$oid": "5fe8fe53ff8d9dc25c9e3277" },
"type": "Video",
"asset": { "$oid": "612549d4778270001862472a" }
}
]
collections:
[
{
"_id": { "$oid": "612fa9f6b2cc520a84e83dde" },
"name": "Name",
"author": { "$oid": "5fe8fe53ff8d9dc25c9e3277" },
"itemsCount": 3,
}
]
我认为以下查询与您的查询相同。
在 运行 之前,它在 artworks.collections
上创建索引(多键索引)
查询
- 根据作者过滤集合
- 使用索引加入正常查找
- 与 1 个集合进行虚拟连接
[{}]
仅用于应用管道 你想要的,就像一个把戏
如果可以的话请测试一下,然后告诉我它是否有效以及速度是否足够快
db.collections.aggregate([
{
"$match": {
"author": {
"$eq": "5fe8fe53ff8d9dc25c9e3277"
}
}
},
{
"$lookup": {
"from": "artworks",
"localField": "_id",
"foreignField": "collections",
"as": "previews"
}
},
{
"$lookup": {
"from": "dummy",
"let": {
"previews": "$previews"
},
"pipeline": [
{
"$set": {
"previews": "$$previews"
}
},
{
"$unwind": {
"path": "$previews"
}
},
{
"$replaceRoot": {
"newRoot": "$previews"
}
},
{
"$sort": {
"date": -1
}
},
{
"$limit": 4
},
{
"$set": {
"id": "$_id"
}
},
{
"$unset": [
"_id"
]
}
],
"as": "previews"
}
}
])