图式数组中的mongoose数
我需要在模式中查找元素,然后统计它们发送的总消息。 我已经尝试了以上代码,但不适合我。
User.find({type: 'psycologist'}).exec(function (err, users) { if(err){ callback(new Error("Something went wrong"), null); }else{ Message.count({userFrom: { "$in" : users} }).exec(function (err, counter) { if(err){ callback(new Error("Something went wrong."), null); }else{ console.log(counter); //displays 0 callback(null, counter); } }); } });
消息架构
var schema = new Schema({ content: {type: String, required: true}, type: {type: String, required: true, default: 'text'}, status: {type: String, default: 'not_read'}, created_at: {type: Date, default: Date.now}, userFrom: {type: Schema.Types.ObjectId, ref: 'User', required: true}, userTo: {type: Schema.Types.ObjectId, ref: 'User', required: true} });
用户架构
var schema = new Schema({ name: {type: String, required: true}, email: {type: String, required: true, unique: true}, phone: {type: String, required: true}, password: {type: String, required: true, select: false}, type: {type: String, required: true}, created_at: {type: Date, required: true, default: Date.now} });
有人知道如何解决这个问题或更好的办法吗? 提前致谢。
如果有任何Mongo专家在这里可以告诉我关于这个查询大量数据的性能的更多细节。
问题是你第一次查找的结果是一组用户,它是完整的文档。 您只能在$ in查找操作符中使用一个数组值。
将其更改为:
User.find({type: 'psycologist'}).exec(function (err, users) { if(err){ callback(new Error("Something went wrong"), null); }else{ var MyUserIdArray = users.map(function(x) { return x._id} ); Message.count({userFrom: { "$in" : MyUserIdArray} }).exec(function (err, counter) { if(err){ callback(new Error("Something went wrong."), null); }else{ console.log(counter); //displays 0 callback(null, counter); } }); } });
一个更好的方法是使用聚合框架来运行一个使用$lookup
操作符的pipe道对来自users
集合的messages
集合执行“左连接”。
考虑运行以下聚合pipe道:
Users.aggregate([ { "$match": { "type": "psycologist"} }, { "$lookup": { "from": "messages", "localField": "_id", "foreignField": "userFrom", "as": "messagesFrom" } }, { "$project": { "messages": { "$size": "$messagesFrom" } } }, { "$group": { "_id": null, "counter": { "$sum": "$messages" } } } ]).exec(function(err, result) { if(err){ callback(new Error("Something went wrong."), null); }else{ console.log(JSON.stringify(result, null, 4)); callback(null, result[0].counter); } });
在上面的聚合操作中,第一步是$match
运算符,它对文档stream进行过滤,只允许匹配的文档未修改地传递到下一个stream水线阶段,并且可以将MongoDB查询语法作为参数。 这与MongoDB Collection的find()
方法和SQL的WHERE
子句以及filter{ "$match": { "type": "psycologist"} }
类似。
User.find({type: 'psycologist'})
在下一个pipe道中,过滤后的文档被传递给$lookup
操作符,该操作对同一数据库中的messages
集合执行左外部连接,以过滤“已连接”集合中的文档进行处理。 “as”选项是要添加到input文档的新数组字段的名称。 新的数组字段包含来自“from”集合的匹配文档。
您将需要获取此数组的长度,因为它指示每个用户的消息数量。 这可以在下一个pipe道中使用$project
操作符来重新生成stream中的每个文档,包括,排除或重命名字段,注入计算字段,使用mathexpression式,date,string和/或逻辑比较,布尔,控制)expression式。
在这种情况下,您使用$size
操作符返回数组中元素的数量,因此您可以获得每个用户的消息数量。
最后的pipe道步骤是汇总所有文档的$group
。 这将通过指定的标识符expression式对input文档进行分组,并应用累加器expression式。 但在这种情况下,您可以指定一个_id
值为null
来计算所有input文档的累计值。 您使用在messages
字段上应用的$sum
累加器运算符(从上一个pipe道计算得出)汇总所有消息计数,从而获得来自特定用户types的消息总数。
尝试
User.find({type: 'psycologist'}, {_id: 1}).exec(function (err, users) { if(err){ callback(new Error("Something went wrong"), null); }else{ var ids = users.map(function(user){ return user._id; }) Message.count({userFrom: { "$in" : ids } }).exec(function (err, counter) { if(err){ callback(new Error("Something went wrong."), null); }else{ console.log(counter); //displays 0 callback(null, counter); } }); } });