gpt4 book ai didi

node.js - Mongoose 在聚合中使用子查询来求和数据

转载 作者:太空宇宙 更新时间:2023-11-03 23:02:49 24 4
gpt4 key购买 nike

我是 Mongoose 的新手。我有这样的模型。

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}

});

我想要获取值为 true 的 Vote 总和的论坛数据。就像这个 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 中我可以通过使用子查询来做到这一点。我怎样才能在 Mongoose 中做到这一点?

最佳答案

使用 MongoDB 服务器 3.4 及更高版本,您可以运行使用 $addFields 的聚合管道。 运算符,其中有 $filter Vote 数组上过滤那些 Kind 属性值匹配 true 的元素,当您获得过滤后的数组时,将其用作<强> $size 运算符,然后计算过滤数组中项目的计数。

考虑以下操作以获得所需的结果:

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"
}
}

根据指定条件选择要返回的数组子集。结果,它返回一个仅包含与条件匹配的元素的数组。

input 属性指的是解析为数组的表达式。在上面,输入是 Votes 数组。

另一个字段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"

as "$$el.Kind" 表达式的计算结果已为 bool 值。

$size 运算符简单地计算数组中的元素数量,因此表达式,例如

{
"$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]
}
}
}
}

表示为

{
"$size": [
{ "Kind": true, "User_id": "58afed97bc343887a9ac9206" },
{ "Kind": true, "User_id": "58b3f0f598501abacd8ff391" }
]
}

并返回以 2 为计数的结果。

对于相反的 DownVote 计数,同样的逻辑适用:

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);
})
<小时/>

对于早期的 MongoDB 版本 3.2,您需要投影文档中的每个其他元素:

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);
})
<小时/>

对于不支持 $filter 的版本 运算符,使用 $setDifference 运算符改为:

Forum.aggregate([
{
"$project": {
"User_id" : 1,
"Title" : 1,
"Content" : 1,
"Tags" : 1,
"isPublic" : 1,
"UpVote" : {
"$size": {
"$setDifference": [
{ "$map": {
"input": "$Vote",
"as": "el",
"in": { "$cond": ["$$el.Kind", "$$el", false] }
}},
[false]
]
}
},
....
....
....
}
}
]).exec((err, results) => {
if (err) throw err;
console.log(results);
})

关于node.js - Mongoose 在聚合中使用子查询来求和数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43084361/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com