Mongodb:高级条件查询

时间:2014-12-18 07:58:06

标签: mongodb

我有以下文件清单:(该集合有超过100个文件)

{name : 'Tom', gender : 'male'},
{name : 'Sandra', gender : 'female'},
{name : 'Alex', gender : 'male'}

我想要的只是返回4条记录,其中2条是男性,2条是女性。

到目前为止,我已经尝试过这个:

db.persons.find({'gender' : { $in : ['male','female']},{$limit : 4});

如预期的那样带来了4条记录,但并不保证有2个男性和2个女性。有没有什么办法可以过滤文件来返回指定的列表,也不需要进行两次单独的数据库调用?

提前致谢。

2 个答案:

答案 0 :(得分:3)

我一直在努力为您的问题找到有效的解决方案,但看起来这并非易事。

我认为可以调用数据库一次的唯一方法是按性别对信息进行分组,然后通过对结果名称数组进行切片并将数组大小限制为2来预测结果名称数组。

这在聚合管道中是不可能的,因为您不能使用$slice等操作符。

尽管如此,我仍然设法按性别对数据库条目进行分组,然后返回数组中的值,然后可以对其进行操作。

经过多次尝试后,我想出了以下解决方案:

var people = db.people.aggregate([
    {
        $group: {
            _id: '$gender',
            names: { $push: '$name'}
        }
    }
]).toArray();

var new_people = [];

for (var i = 0; i < people.length; i++) {
    for (var j = 0; j < 2; j++) {
        new_people.push({
            gender: people[i]._id,
            name: people[i].names[j]
        });
    }
}

如果您想过滤数据,您可以根据我的示例选择两个选项:

  • $match阶段

  • 内的汇总管道中过滤数据
  • 循环聚合结果数组时过滤数据

答案 1 :(得分:1)

拨打两个电话很容易,我认为没有理由不制作它们。

收集两个find的结果:

var males = db.person.find({"gender": "male"}, {"name":1}).limit(2);
var females = db.person.find({"gender": "female"}, {"name":1}).limit(2);
var all = [];
var collectToAll = function(person) { all.push(person); };
males.forEach(collectToAll)
females.forEach(collectToAll)

然后all

[
        {
                "_id" : ObjectId("549289765732b52ca191fdae"),
                "name" : "Tom"
        },
        {
                "_id" : ObjectId("549289865732b52ca191fdb0"),
                "name" : "Alex"
        },
        {
                "_id" : ObjectId("549289805732b52ca191fdaf"),
                "name" : "Sandra"
        }
]