难道没人知道?在nodejs中使用聚合框架效率高,来取mongodb内嵌文档,只要一条?
发布于 12 年前 作者 sogego 14485 次浏览 最后一次编辑是 8 年前

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

17 回复

这个是无法实现的好像

自己建一个主键 不要用_id就行了 呵呵 等待大神解答通过_id获取数据的方法

拿到数据以后自己排除一下吧…

没人知道吗?

http://mongoosejs.com/docs/subdocs.html 这个里面的Finding a sub-document不是么

@zs1621 Each document has an _id. DocumentArrays have a special id method for looking up a document by its _id. 每一个文档都有一个_id,即便建立的是一个子文档,mongoose总会为他增加一个_id,我们可以通过这个_id来查询子文档,但是他要问的是能不能通过name来查询子文档,或者说通过子文档的非主键条件来查询。 @sogego 这显然是不可能的,除非你建立2个文档分开存储还可以这么取,否则父子文档存放在一起,目前是没有api能根据非id条件从父文档对象中查询子文档对象的。

@a272121742 我只要得到 如下的数据格式,带有Person的属性name 和 只有一条子文档的全部属性。 var person = { name: ‘zhangsan’, friends: [ { { _id:ObjectID, name:‘wangwu’, phone:‘456’ } ] }

就是我只想看到 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条吧。

嗯,你的问题我也不懂,我只能说如果内嵌文档在不断更新变大的话,就不适合作为内嵌文档了

使用聚合框架终于搞定

@sogego mongoose暂时做不到应该,或者说我没用到。分析了下也觉得mongoose很难做到,除非有其他的工具

@a272121742 lz已经解决了 –

如果追求效率高,直接调用mongodb的原生js查询,配合index,何必还要框架呢。

怎么总有人挖坟。。

建议陈旧的帖子被顶了也上不来

哈哈 原来mongodb支持这么多种聚合 http://docs.mongodb.org/manual/core/aggregation-introduction/ 感觉自己有点孤陋寡闻啊·· aggregate中文文档: http://www.w3cschool.cc/mongodb/mongodb-aggregate.html

回到顶部