我正在尝试在子文档中搜索。这是我的文档结构:
{
_id: <ObjectID>,
email: ‘test@emample.com’,
password: ‘12345’,
images: [
{
title: ‘Broken Hand’,
description: ‘Here is a full description’,
comments: [
{
comment: ‘Looks painful’,
}
],
tags: [‘hand’, ‘broken’]
}
]
}
我希望能够找到所有具有特定标记的用户的所有图像,但我使用的查询只返回它找到的第一个带有该标记的图像:
db.site_users.find({'images.tags': "broken"}, {images: 1, images: {$elemMatch: { 'tags': 'broken'}}}).pretty()
有人可以指出我如何获得所有图像的正确方向吗?
答案 0 :(得分:0)
您可以使用aggregation framework:
db.site_users.aggregate([
{$unwind: "$images"},
{$match:{
"images.tags": "broken"
}}
])
答案 1 :(得分:0)
查询很好,因为它与文档匹配,但“投影”超出了您使用.find()
所能做的范围,您需要.aggregate()
并且需要注意不要删除“图像“数组中的项目,只有不匹配的”标签“。
理想情况下,您使用$filter
内的$project
对MongoDB 3.2执行此操作:
db.site_users.aggregate([
{ "$match": { "images.tags": "broken" }},
{ "$project": {
"email": 1,
"password": 1,
"images": {
"$filter": {
"input": "$images",
"as": "image",
"cond": {
"$setIsSubSet": [["broken"], "$$image.tags"]
}
}
}
}}
])
或者可能使用与MongoDB 2.6兼容的$map
和$setDifference
,只要“images”内容对于每个条目都是“唯一的”。这是由于“设置”操作,其中“集合”是“唯一的”:
db.site_users.aggregate([
{ "$match": { "images.tags": "broken" }},
{ "$project": {
"email": 1,
"password": 1,
"images": {
"$setDifference": [
{ "$map": {
"input": "$images",
"as": "image",
"in": {
"$cond": {
"if": { "$setIsSubSet": [["broken"], "$$image.tags" ] },
"then": "$$image",
"else": false
}
}
}},
[false]
]
}
}}
])
可以在早期版本的MongoDB中完成,但由于在阵列上处理$unwind
的成本,最好避免使用它:
db.site_users.aggregate([
{ "$match": { "images.tags": "broken" }},
{ "$unwind": "$images" },
{ "$match": { "images.tags": "broken" }},
{ "$group": {
"_id": "$_id",
"email": { "$first": "$email" },
"password": { "$first": "$password" },
"images": { "$push": "$images" }
}}
])
由于在您没有“聚合”任何内容的情况下使用$unwind
通常需要相当大的成本,那么如果您没有其他实用方法可用的现代版本,那么通常最好接受在客户端代码而不是服务器上“过滤”数组内容本身。
因此,对于这种情况,您应该只使用$unwind
,这样可以通过删除不匹配项目的顺序“显着”减少数组条目。否则,处理成本可能大于传输数据的网络成本,任何好处都会被否定。
如果您没有现代版本,请获取一个。这些功能与实用和高效的功能完全不同。