MongoDB-仅检索匹配的子文档和根文档
编辑: 问题已解决,请参见下文 我有以下文件:MongoDB-仅检索匹配的子文档和根文档,mongodb,Mongodb,编辑: 问题已解决,请参见下文 我有以下文件: db.clients.insert({ _id: ObjectId("524d720d8d3ea014a52e95bb"), company: "Example", logins: [ { "name": "John Smith", "username": "test", "password": "eF9wnBEys0OzL5vmR/OH
db.clients.insert({
_id: ObjectId("524d720d8d3ea014a52e95bb"),
company: "Example",
logins: [
{
"name": "John Smith",
"username": "test",
"password": "eF9wnBEys0OzL5vmR/OHGCaekHiw/Miy+XvbDdayxeo=",
"email": "a@a.com",
"last": null,
"roles": ["CONFIG"]
},
{
"name": "Guest",
"username": "guest",
"password": "K/gYODb7XPo0erySvL276DyPi4+stPPK4jM3pJ8aaVg=",
"email": "a@a.com",
"last": null,
"roles": []
}
]
});
现在,我想用这个文档对我的客户进行身份验证。但是,我不想检索每个子登录,我只想要一个匹配的
这就是我使用聚合的原因:
db.clients.aggregate(
{
"$project": {
"login": "$logins",
"_id": 0
}
},
{
"$unwind": "$login"
},
{
"$group": {
"_id": "$login.username",
"login": {
"$first": "$login"
}
}
},
{
"$match": {
"login.username": "test",
"login.password": "eF9wnBEys0OzL5vmR/OHGCaekHiw/Miy+XvbDdayxeo=",
}
}
);
这很好,给了我:
{
"result" : [
{
"_id" : "test",
"login" : {
"name" : "John Smith",
"username" : "test",
"password" : "eF9wnBEys0OzL5vmR/OHGCaekHiw/Miy+XvbDdayxeo=",
"email" : "a@a.com",
"last" : null,
"roles" : [
"CONFIG"
]
}
}
],
"ok" : 1
}
但现在,棘手的部分是,我还想检索根文档字段。例如\u id
和公司
但不管我怎么努力,我都做不到。你有解决办法吗?:)
编辑: 好吧,事实上这并不难。对不起
db.clients.aggregate(
{
"$project": {
"login": "$logins",
"_id": "$_id",
"company": "$company"
}
},
{
"$unwind": "$login"
},
{
"$group": {
"_id": "$login.username",
"login": {
"$first": "$login"
},
"clientId": {
"$first": "$_id"
},
"company": {
"$first": "$company"
},
}
},
{
"$match": {
"login.username": "test",
"login.password": "eF9wnBEys0OzL5vmR/OHGCaekHiw/Miy+XvbDdayxeo=",
}
}
);
略短一点的变体:
db.clients.aggregate(
{$match:{"logins.username":"test"}},
{$unwind:"$logins"},
{$match:{"logins.username":"test","logins.password":"eF9wnBEys0OzL5vmR/OHGCaekHiw/Miy+XvbDdayxeo="}}
)
输出为:
{
"result" : [
{
"_id" : ObjectId("524d720d8d3ea014a52e95bb"),
"company" : "Example",
"logins" : {
"name" : "John Smith",
"username" : "test",
"password" : "eF9wnBEys0OzL5vmR/OHGCaekHiw/Miy+XvbDdayxeo=",
"email" : "a@a.com",
"last" : null,
"roles" : [
"CONFIG"
]
}
}
],
"ok" : 1
}
您也可以使用
查找和位置投影操作符来执行此操作:
db.clients.find({
“logins.username”:“测试”,
“登录密码”:“eF9wnBEys0OzL5vmR/OHGCaekHiw/Miy+XvbDdayxeo=”,
}, {
“登录。$”:1,
“公司”:1
})
投影中的$
包含查询中匹配的登录
数组元素的索引
输出:
{
“_id”:ObjectId(“524d720d8d3ea014a52e95bb”),
“公司”:“示例”,
“登录”:[
{
“姓名”:“约翰·史密斯”,
“用户名”:“测试”,
“密码”:“eF9wnBEys0OzL5vmR/OHGCaekHiw/Miy+XvbDdayxeo=”,
“电子邮件”:a@a.com",
“last”:空,
“角色”:[
“配置”
]
}
]
}
所以请对您自己的问题发表一个答案,没关系。我是stackoverflow的新手,所以我的声誉很低。我不能在8小时前回答我自己的问题:)我想你需要在{$match:{“logins.username:“test”}}
之前先解开。不,你不需要解开。因为,这样做一个数组检查级别?数组的所有元素都会被检查。是否可以只返回子文档中选定的字段?ie仅登录
名称
?我尝试了登录。$.name
但它返回了整个子文档。@user1063287我本以为可以。最好发布一个新的问题和细节。