首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用mongodb进行管道操作

用mongodb进行管道操作
EN

Stack Overflow用户
提问于 2014-04-25 19:52:03
回答 2查看 1.2K关注 0票数 1

我对mongo很陌生,我正在寻找一种使用单个命令进行排序和删除的干净方法:

代码语言:javascript
复制
{u'house_id': 199, u'_id': ObjectId('50906d7fa3c412bb040eb896'), u'type': u'house', u'rate': 58.09608083191365}
{u'house_id': 199, u'_id': ObjectId('50906d7fa3c412bb040eb895'), u'type': u'house', u'rate': 49.34223066136407}
{u'house_id': 198, u'_id': ObjectId('50906d7fa3c412bb040eb891'), u'type': u'house', u'rate': 76.18366499496366}
{u'house_id': 198, u'_id': ObjectId('50906d7fa3c412bb040eb892'), u'type': u'house', u'rate': 17.46279901047208}

如何删除具有相同house_id的最低速率的文档?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-04-25 22:11:34

不幸的是,remove和update命令还不允许它们中的通用游标方法( https://jira.mongodb.org/browse/SERVER-1599 ),所以目前最好的方法是先查找,然后删除:

代码语言:javascript
复制
var houses = db.collection.find({house_id: 199}).sort({rate: 1});
houses.forEach(function(doc){
    db.collection.remove({_id: house._id});
    return;
})

这是目前最好的办法。

票数 1
EN

Stack Overflow用户

发布于 2014-06-02 02:25:39

虽然这里的基本答案是您需要循环结果,但通过一次命中获得所有“最小值”文档,您可能会做得更好。聚合框架对此非常有用,因为您可以将$first运算符与$sort组合在一起。

代码语言:javascript
复制
var result  = db.collection.aggregate([
    { "$sort": { 
        "house_id": 1,
        "rate": 1
    }},
    { "$group": {
        "_id": "$house_id",
        "docId": { "$first": "$_id" },
        "count": { "$sum": 1 }
    }},
    { "$match": {
        "count": { "$gt": 1 }
    }}
])

这会给出包含所有文档的结果,这些文档在集合中具有最低的比率,当然,如果您不想删除"house_id“,则会丢弃任何只有一个值的结果。

然后,如果您真的可以将所有这些结果应用到$in操作符中,只需进行一点映射,就可以提取您需要的_id值:

代码语言:javascript
复制
var ids = [];
result.result.forEach(function(doc) {
    ids.push( doc.docId );
});

db.collection.remove({ "_id": { "$in": ids } })

另外,注意到默认形式的.remove()将对所有匹配的文档起作用,除非指定了一个可选操作符来删除一个。但这对我来说没问题。

在MongoDB 2.6中,您可以访问与聚合结果一起返回的“游标”,因此可以选择在大型结果集上改进这一点:

代码语言:javascript
复制
var ids = [];
var cursor = db.collection.aggregate([
    { "$sort": { 
        "house_id": 1,
        "rate": 1
    }},
    { "$group": {
        "_id": "$house_id",
        "docId": { "$first": "$_id" },
        "count": { "$sum": 1 }
    }},
    { "$match": {
        "count": { "$gt": 1 }
    }}
]);

cursor.forEach(function(doc) {
    ids.push( doc.docId );

    if ( ids.length % 500 == 0 ) {
        db.collection.remove({ "_id": { "$in": ids } });
        ids = [];
    }

});

if ( ids.length > 0 )
    db.collection.remove({ "_id": { "$in": ids } });

或基本结构的任何语言的一般实现。

因此,您不完全是“管道”或“子查询”结果,因为这样的操作是不受支持的。但是,$in运算符是在这里高效组合的方法,也是聚合的方法,为您找到“最低”结果提供了一种有效的方法。

通常,它应该比在这里使用.find()以及.sort().limit(1)修饰符循环所有可能的“.sort()”值更有效。

另外,与其他建议相反,您将不会删除“所有”您的文档,甚至可能是这样,如果您只是将.limit(1)添加到您的查找中(如未显示的那样),即您不知道是否只有一个结果。而且您可能不想删除您唯一的文档。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23301805

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档