子文档数组属性上的范围查询

时间:2015-12-30 18:27:41

标签: mongodb

我有一系列配方服务的食谱。每份食物都有数字能量属性。我需要选择至少一份能量落在给定范围内的食谱。

例如我有2个食谱:

{
  title: 'Greek salad',
  servings: [
    {
      energy: 100
    },
    {
      energy: 150
    }
  ]
},
{
  title: 'Smashed potatoes',
  servings: [
    {
      energy: 150
    },
    {
      energy: 200
    }
  ]
}

我正在寻找一个仅与Greek salad匹配的查询,范围为90..110,以及140..160范围内的两个食谱。

我想出的最好的:

db.recipes.find({$and: [
    {'servings.energy' : {$gt: 90}}, 
    {'servings.energy' : {$lt: 110}}
   ]}

匹配2个结果,这不是预期的结果。

PS。集合中有1M +条记录,我正在寻找一个完全不依赖索引的查询。也许我可以某种方式改变数据结构以满足我的需求?

2 个答案:

答案 0 :(得分:1)

您可以使用以下聚合查询来获得您期望的结果:

    db.testso.aggregate([
                  {$match: { "servings.energy": { $gt: 90, $lt:110 }}},   
                  {$unwind:"$servings"},
                  {$match: { "servings.energy": { $gt: 90, $lt:110 }}}
]);
  1. 首先根据您的条件匹配记录 - 这将从您的子文档中获取两个记录。
  2. 现在根据服务数组展开记录。
  3. 现在再次根据您的条件匹配记录。

答案 1 :(得分:1)

您可以使用mongodb $filter运算符执行此操作:

db.getCollection('recipes').aggregate([
  {$project: {
    recipe: "$$ROOT",
    servings: {$filter: {
        input: "$recommendedServings",
        as: "serving",
        cond: {
            $and: [{$gt: ['$$serving.energy', 400]}, 
                   {$lt: ['$$serving.energy', 410]}]
        } 
     }}
   }},
   {$match: {"servings.0": {$exists: true}}}
 ])