查询多个日期范围,仅返回MongoDB中的特定键

时间:2014-01-08 17:14:46

标签: mongodb

在Mongo中,我的文档如下所示:

dateRange: [{
    "price": "200",
    "dateStart": "2014-01-01",
    "dateEnd": "2014-01-30"
},

{
    "price": "220",
    "dateStart": "2014-02-01",
    "dateEnd": "2014-02-15"
}]

好看又简单吧?只是日期和价格。现在,我是一个棘手的派对,我将如何创建一个查询以找到适合2014-01-12的dateRange,然后在找到它之后返回价格而不是整个dateRanges数组?

这些dateRanges可以变得非常大,我正在尝试最小化返回的数据量(如果Mongo可以实现这一点)。注意,我可以根据需要更改日期格式,我只是使用上面的例子。

感谢任何帮助,谢谢!

2 个答案:

答案 0 :(得分:1)

您想使用$elemMatch运算符,该运算符仅在版本2.2向上有效。您还需要确保使用multikey indexes

编辑:要明确,您还必须使用评论$elemMatch find operator中指出的below

话虽如此,我同意mnemosyn的评论要点。将数组的每个元素表示为单个文档会更好。

$ elemMatch的快速示例,用于演示投影。只需在查找中添加$ elemMatch。

> db.test.save ( {
  _id: 1,
  zipcode: 63109,
  students: [
               { name: "john", school: 102, age: 10 },
               { name: "jess", school: 102, age: 11 },
               { name: "jeff", school: 108, age: 15 }
            ]
 } );

> db.test.find( { zipcode: 63109 }, { students: { $elemMatch: { school: 102 } } } ).pretty() );
{
    "_id" : 1,
    "students" : [
        {
            "name" : "john",
            "school" : 102,
            "age" : 10
        }
    ]
}

答案 1 :(得分:0)

嗯,该模式的问题在于它使用大型嵌入式数组 - 这可能效率很低,因为mongodb查询总是会找到一个文档,而不是嵌入对象的子集。即使您正在使用投影,mongodb也必须在内部读取整个对象,因此如果数组变得很大,比如100k条目,那将会使事情变得迟钝。

为什么不简单地将这些数组元素分成文档,例如

{ 
  price : 200,
  productId : ObjectId("foo"), // or whatever the price refers to
  dateStart : "2014-01-01",
  dateEnd : "2013-01-30"
}

这样,mongodb不需要使用所有价格来拉动整个对象,而只需要与您的日期范围匹配的价格。这将最大限度地减少传输的数据量。然后,您还可以使用query projection仅返回price,即db.collection.find({ criteria }, {"price" : 1, "_id" : 0})

当然,对象的数量会急剧增加,但有效的索引将解决这个问题。引起的唯一低效率是productId的重复,这比处理大型嵌入式阵列便宜。

P.S:我建议使用实际日期(ISODate)而不是字符串,即使它们的格式是可排序的。