所以这是交易,我使用的是Mongoose,我有一个PollOptionSchema,里面有选民名单
java.security
数据库中的一个文档是这样的
let PollOptionSchema: mongoose.Schema = new Schema({
name: String,
voters: [{ user: { type: Schema.Types.ObjectId, ref: 'User' }, time: { type: Date, default: Date.now } }]
});
我想得到的是这个PollOption Documents只有id等于查询参数的用户。换句话说,如果$ userid =“56b0487a9f10c4e3d1012aff”,我想得到下面的文档。通常,“选民”中只有一个元素会返回。
{
"_id": {
"$oid": "56a8365fa619b9466d422ef7"
},
"name": "more",
"voters": [
{
"user": {
"$oid": "56a98ab1bc6279200c39c276"
},
"_id": {
"$oid": "56a98ac0bc6279200c39c277"
},
"time": {
"$date": "2016-01-28T03:28:00.090Z"
}
},
{
"user": {
"$oid": "56b0487a9f10c4e3d1012aff"
},
"_id": {
"$oid": "56b04e0fd889825ad7932336"
},
"time": {
"$date": "2016-02-02T06:34:55.254Z"
}
}
],
"__v": 2
}
我已尝试过以下代码($ userId是客户端的参数)
{
"_id": {
"$oid": "56a8365fa619b9466d422ef7"
},
"name": "more",
"voters": [
{
"user": {
"$oid": "56b0487a9f10c4e3d1012aff"
},
"_id": {
"$oid": "56b04e0fd889825ad7932336"
},
"time": {
"$date": "2016-02-02T06:34:55.254Z"
}
}
],
"__v": 2
}
但上面的查询只返回null。我已经在网上搜索了很长时间但找不到解决方案。
非常感谢任何帮助。
答案 0 :(得分:1)
您有三种方法可以解决此问题,所有这些方法都使用 aggregation framework 来返回所需的结果。使用 aggregate()
方法,您可以使用 $filter
运算符返回voters
数组,其中只包含与过滤条件匹配的元素,这适用于MongoDB 3.2版。那你怎么样呢?
嗯,以下示例演示了这一点:
// Define the pipeline
var pipeline = [
{
"$match": { "voters.user": userId }
},
{
"$project": {
"name": 1,
// Use the $filter on the voters array
"voters": {
"$filter": {
"input": "$voters",
"as": "el",
"cond": {
"$eq": [ "$$el.user", userid ]
}
}
}
}
}
];
// Run the aggregation pipeline
optionModel.aggregate(pipeline, function (err, result){
if(err) { /* Handle error */ }
console.log(result);
});
或者使用 aggregate()
方法上的流畅API运行聚合:
optionModel.aggregate()
.match({ "$match": { "voters.user": userId } })
.project({
"name": 1,
// Use the $filter on the voters array
"voters": {
"$filter": {
"input": "$voters",
"as": "el",
"cond": {
"$eq": [ "$$el.user", userid ]
}
}
}
})
.exec(function (err, result){
if(err) { /* Handle error */ }
console.log(result);
});
对于MongoDB版本< 3.2,其他替代方法是使用 $map
和 $setDifference
的组合来过滤数组中的内容,如下所示:
// Define the pipeline
var pipeline = [
{
"$match": { "voters.user": userId }
},
{
"$project": {
"name": 1,
// Use $map and $setDifference on the voters array
"votes": {
"$setDifference": [
{
"$map": {
"input": "$votes",
"as": "el",
"in": {
"$cond": [
{ "$eq": [ "$$el.user", userId ] },
"$$el",
false
]
}
}
},
[false]
]
}
}
}
];
或者较弱的高性能查询 $unwind
:
// Define the pipeline
var pipeline = [
{
"$match": { "votes.user": userId }
},
{ "$unwind": "$votes" },
{
"$match": { "votes.user": userId }
},
{
"$group": {
"_id": "$_id",
"votes": { "$push": "$votes" },
"name": { "$first": "$name" }
}
}
];