Nodejs中使用聚合框架效率高,来取mongodb内嵌文档只要一条?
Nodejs中使用聚合框架效率高,来取mongodb内嵌文档只要一条?
var PersonSchema = new Schema({ name: {type: String}, friends: [ { name: {type: String}, phone: {type: String}, } ] });
mongoose.model(‘Person’,PersonSchema);
实体数据如下: var person = { name: ‘zhangsan’, friends: [ { _id:ObjectID, name:‘lisi’, phone:‘123’ }, { _id:ObjectID, name:‘wangwu’, phone:‘456’ }, { _id:ObjectID, name:‘zhaoliu’, phone:‘789’ } ] }
我现在只要得到 friends中 name=='wangwu’的数据,仅此一条, 如何操作呢。
Person.findOne({_id: 已知}) .exec(function(error,success){ console.log(success); //这个success中是全部的friends });
有没有直接findOne到当前文档的嵌套部分的指定_id呢
==============研究了两天 终于搞定 推荐大家使用============= // 聚合框架效率高 var now=new Date(); Person.aggregate( {$match: {_id: ‘这个已知是个参数’}}, //首先去match这个人的ID,取得一条 {$project: {friends: 1,_id: 0,name:1}}, //为1表示要这个属性,为0表示不要 {$unwind: ‘$friends’}, //展开friends 子文档 数组 {$match: {‘friends._id’: ‘这个已知是个参数,比如是从friends列表中取的’}}, //取match {$group: { //组织要output的 friends:{$push: ‘$friends’}, _id: null, name: {$first: ‘$name’} } }, function(error,reply){ var buffer = reply[0].chapter[0]; // console.log(’======= ',buffer); //测试的时候可以放开,运行时必须去掉,因为会影响处理速度,当friends为100条时,只用了5ms就搞定了。 console.log(‘time :’+(new Date().getTime()-now.getTime())+‘ms’); } );
-----------------------------------处理同样的数据要25ms左右,是聚合框架查询的5倍---------------------- // 普通查询效率低 // Person.findOne({_id: ‘这个已知是个参数’}) // .select(‘friends’) // .exec(function(error,detail){ // if(error || !detail){ // return; // } var buffer = []; // for(var i= 0,len = detail.friends.length;i < len; i += 1){ // friends= detail.friends[i]; // if(这个已知是个参数,比如是从friends列表中取的 === friends._id){ // buffer = friends; // } // } console.log(buffer); // tools.log(‘time :’+(new Date().getTime()-now.getTime())+‘ms’); // });
Nodejs中使用聚合框架效率高,来取mongodb内嵌文档只要一条?
在处理MongoDB中的嵌套文档时,我们经常会遇到需要从一个数组中找到特定元素的情况。假设我们有一个Person
模型,其中包含一个名为friends
的嵌套数组。现在我们需要从这个数组中找到一个特定的朋友信息。
示例模型定义
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
var PersonSchema = new Schema({
name: { type: String },
friends: [
{
name: { type: String },
phone: { type: String },
}
]
});
mongoose.model('Person', PersonSchema);
示例数据
const person = {
name: 'zhangsan',
friends: [
{
_id: ObjectId(), // 假设这是Mongoose生成的ObjectId
name: 'lisi',
phone: '123'
},
{
_id: ObjectId(),
name: 'wangwu',
phone: '456'
},
{
_id: ObjectId(),
name: 'zhaoliu',
phone: '789'
}
]
};
使用聚合框架获取特定朋友
如果我们想要找到friends
数组中name
为wangwu
的朋友信息,可以使用MongoDB的聚合框架(Aggregation Framework)来实现:
const Person = mongoose.model('Person');
const now = new Date();
Person.aggregate([
{ $match: { _id: ObjectId('已知的ObjectId') } }, // 匹配特定的Person文档
{ $project: { friends: 1, _id: 0, name: 1 } }, // 选择要输出的字段
{ $unwind: '$friends' }, // 展开friends数组
{ $match: { 'friends.name': 'wangwu' } }, // 匹配特定的朋友
{ $group: {
_id: null,
friend: { $first: '$friends' },
name: { $first: '$name' }
}}
], function (error, reply) {
if (error) {
console.error(error);
} else {
console.log(reply[0].friend); // 输出找到的朋友信息
console.log('time: ' + (new Date().getTime() - now.getTime()) + 'ms');
}
});
解释
- $match: 首先匹配特定的
Person
文档。 - $project: 选择要输出的字段,这里我们选择了
friends
数组和name
字段,但不包括_id
字段。 - $unwind: 将
friends
数组展开成多个文档。 - $match: 匹配
friends
数组中name
为wangwu
的文档。 - $group: 将匹配的结果重新组合成一个新的文档,并提取第一个匹配的朋友信息。
这种方式利用了聚合框架的强大功能,能够高效地从嵌套文档中获取所需的信息,比传统的查询方式更快。
这个是无法实现的好像
自己建一个主键 不要用_id就行了 呵呵 等待大神解答通过_id获取数据的方法
拿到数据以后自己排除一下吧…
没人知道吗?
http://mongoosejs.com/docs/subdocs.html 这个里面的Finding a sub-document不是么
就是我只想看到 zhangsan的第二个朋友的name和phone 如果用,person.friends 去循环,再与子文档的_id比较,也是可以得到的,但如果子文档有10000个朋友,我们就要循环10000次的match。 var f = person.friends; //这个可以能过ID取得 var buffer = []; for(var i=0,len=f.length;i < len; i += 1){ if( f[i]._id === 传入的参数){ buffer.push( f[i]); }
}
console.log(buffer); 这样是可以得到的。如果数据量大了,怎么办。一条微薄有10000个回复,我们总不能去mathc这10000条吧。
嗯,你的问题我也不懂,我只能说如果内嵌文档在不断更新变大的话,就不适合作为内嵌文档了
使用聚合框架终于搞定
如果追求效率高,直接调用mongodb的原生js查询,配合index,何必还要框架呢。
怎么总有人挖坟。。
哈哈 原来mongodb支持这么多种聚合 http://docs.mongodb.org/manual/core/aggregation-introduction/ 感觉自己有点孤陋寡闻啊·· aggregate中文文档: http://www.w3cschool.cc/mongodb/mongodb-aggregate.html
貌似很吊
在Node.js中使用Mongoose与MongoDB交互时,如果你想要从一个内嵌文档数组中获取特定条件的一条记录,使用聚合框架(Aggregation Framework)可以提高查询效率。下面是一个具体的例子,展示了如何通过聚合框架查询嵌套文档。
示例代码
const mongoose = require('mongoose');
const { ObjectId } = mongoose.Types;
// 假设已经定义好了Person模型
const Person = mongoose.model('Person', new mongoose.Schema({
name: String,
friends: [{
name: String,
phone: String,
_id: ObjectId
}]
}));
async function findFriendById(personId, friendId) {
const result = await Person.aggregate([
{ $match: { _id: mongoose.Types.ObjectId(personId) } }, // 匹配指定的Person
{ $project: { friends: 1, _id: 0, name: 1 } }, // 投影需要的字段
{ $unwind: '$friends' }, // 展开friends数组
{ $match: { 'friends._id': mongoose.Types.ObjectId(friendId) } }, // 匹配朋友的_id
{
$group: {
_id: null,
name: { $first: '$name' },
friends: { $push: '$friends' }
}
}
]);
if (result && result.length > 0) {
return result[0].friends[0]; // 返回匹配的朋友
} else {
return null;
}
}
// 使用示例
findFriendById('已知person的_id', '已知friend的_id')
.then(friend => {
console.log(friend);
})
.catch(err => {
console.error(err);
});
解释
- $match: 首先匹配指定的
Person
文档。 - $project: 只选择需要的字段(这里选择了
friends
数组和name
字段)。 - $unwind: 将
friends
数组展开成多个独立的文档。 - $match: 在展开后的文档中匹配特定的朋友。
- $group: 最后将符合条件的朋友重新组织成一个文档,并输出。
这种方式避免了循环遍历数组,因此在处理大量数据时效率更高。