我是猫鼬新手。我有这样的模特。
var ForumSchema = new mongoose.Schema({
User_id : {type : Schema.Types.ObjectId, ref : 'User'},
Title : {type : String},
Content : {type : String},
Tags : [{type : String}],
isPublic : {type : Boolean, default : false},
Vote : [{
User_id : {type : Schema.Types.ObjectId, ref : 'User'},
Kind : {type : Boolean}
}],
Rate : [{
User_id : {type : Schema.Types.ObjectId, ref : 'User'},
Count : {type : Number}
}],
Comment : [{
User_id : {type : Schema.Types.ObjectId, ref : 'User'},
Content : String,
Created_at : {type : Date, required : true, default : Date.now}
}],
Created_at : {type : Date, required : true, default : Date.now},
Updated_at : {type : Date}
});
我希望获得Vote
之和值为true的论坛数据。像这样的json。
{
[
_id : <Some object id>,
User_id : <Some object id from User Model>,
Title : <Title>,
Content : <Content>,
Tags : [Some array],
isPublic : true,
UpVote : 23,
....
....
....
]
}
在mysql中,我可以使用子查询来完成此操作。我怎么能在猫鼬中做到这一点?
答案 0 :(得分:3)
使用MongoDB服务器3.4及更高版本,您可以运行使用 $addFields
运算符的聚合管道,该运算符在{强> $filter
上{1}}数组用于过滤那些Vote
属性值与true匹配的元素,当您获得过滤后的数组时,将其用作 $size
运算符的输入表达式然后计算过滤数组中项目的计数。
考虑以下操作以获得所需的结果:
Kind
在上面,内部表达
Forum.aggregate([
{
"$addFields": {
"UpVote": {
"$size": {
"$filter": {
"input": "$Vote",
"as": "el",
"cond": "$$el.Kind"
}
}
}
}
}
]).exec((err, results) => {
if (err) throw err;
console.log(results);
})
根据指定的条件选择要返回的数组的子集。因此,它返回一个只包含那些符合条件的元素的数组。
{
"$filter": {
"input": "$Vote",
"as": "el",
"cond": "$$el.Kind"
}
}
属性是指解析为数组的表达式。在上面,输入是Votes数组。
另一个字段 input
表示输入数组中元素的变量名称。 as
表达式通过此变量访问输入数组中的每个元素。
as
字段包含一个表达式,用于确定是否在结果数组中包含该元素。表达式通过 cond
中指定的变量名访问元素。
所以在上面,如果被评估的数组中的元素的as
子属性等于Kind
,由表达式true
表示,则条件匹配且元素为包含在要返回的子集中。
举一个简单的例子,举个例如这个高级表达式:
"$$el.Kind"
返回数组
{
"$filter": {
"input": [
{ "Kind": true, "User_id": "58afed97bc343887a9ac9206" },
{ "Kind": false, "User_id": "58ad50a429b2961777f91c97" },
{ "Kind": true, "User_id": "58b3f0f598501abacd8ff391" }
],
"as": "el",
"cond": {
"$eq": ["$$el.Kind", true]
}
}
}
条件部分
[
{ "Kind": true, "User_id": "58afed97bc343887a9ac9206" },
{ "Kind": true, "User_id": "58b3f0f598501abacd8ff391" }
]
可以简化为
"cond": {
"$eq": ["$$el.Kind", true]
}
因为"cond": "$$el.Kind"
表达式已经计算为布尔值。
$size
运算符可以简单地计算数组中元素的数量,从而计算表达式,例如
"$$el.Kind"
表示为
{
"$size": {
"$filter": {
"input": [
{ "Kind": true, "User_id": "58afed97bc343887a9ac9206" },
{ "Kind": false, "User_id": "58ad50a429b2961777f91c97" },
{ "Kind": true, "User_id": "58b3f0f598501abacd8ff391" }
],
"as": "el",
"cond": {
"$eq": ["$$el.Kind", true]
}
}
}
}
并以2作为计数返回结果。
对于相反的DownVote计数,同样的逻辑适用:
{
"$size": [
{ "Kind": true, "User_id": "58afed97bc343887a9ac9206" },
{ "Kind": true, "User_id": "58b3f0f598501abacd8ff391" }
]
}
对于早期的MongoDB版本3.2,您需要预测文档中的每个其他元素:
Forum.aggregate([
{
"$addFields": {
"UpVote": {
"$size": {
"$filter": {
"input": "$Vote",
"as": "el",
"cond": "$$el.Kind"
}
}
},
"DownVote": {
"$size": {
"$filter": {
"input": "$Vote",
"as": "el",
"cond": { "$not": ["$$el.Kind"] }
}
}
}
}
}
]).exec((err, results) => {
if (err) throw err;
console.log(results);
})
对于不支持 $filter
运算符的版本,请使用 $setDifference
运算符代替:
Forum.aggregate([
{
"$project": {
"User_id" : 1,
"Title" : 1,
"Content" : 1,
"Tags" : 1,
"isPublic" : 1,
"UpVote" : {
"$size": {
"$filter": {
"input": "$Vote",
"as": "el",
"cond": "$$el.Kind"
}
}
},
....
....
....
}
}
]).exec((err, results) => {
if (err) throw err;
console.log(results);
})
答案 1 :(得分:0)
你可以在mongodb中使用聚合
db.getCollection('forum').aggregate([{
$unwind: "$Vote"
},
{
$match: {
"Vote. Kind": true
}
},
{
$group: {
_id: '$_id',
"User_id": {
'$first': '$User_id'
},
"Title": {
'$first': '$Title'
},
UpVote: {
$sum: 1
}
}
}
])
你也可以在mongoose中使用同样的查询,最后你得到的票数