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

查询多个日期范围,只返回MongoDB中的特定键,mongodb,Mongodb,在Mongo中,我有一个如下所示的文档: dateRange: [{ "price": "200", "dateStart": "2014-01-01", "dateEnd": "2014-01-30" }, { "price": "220", "dateStart": "2014-02-01", "dateEnd": "2014-02-15" }] 又好又简单,对吧?只是日期和价格。现在,我面临的棘手问题是,如何创建一个查询来查找适合2014

在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的日期范围,然后在找到后返回价格,而不是整个日期范围数组

这些日期范围可能会变得相当大,我正在尝试最小化返回的数据量(如果Mongo能够做到这一点的话)。请注意,如果需要,我可以更改日期格式,我只是出于示例目的使用上述格式


感谢您的帮助,谢谢

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

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

{ 
  price : 200,
  productId : ObjectId("foo"), // or whatever the price refers to
  dateStart : "2014-01-01",
  dateEnd : "2013-01-30"
}
通过这种方式,mongodb不需要以所有价格拉动整个对象,而只需要与日期范围匹配的价格。这将最大限度地减少传输的数据量。然后,您还可以使用仅返回
price
,即
db.collection.find({criteria},{price:1,{u id:0})

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

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

您希望使用运算符,它仅在2.2版以上版本中有效。您还需要确保使用

编辑:为了清楚起见,您还必须使用注释中指出的

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

$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
        }
    ]
}

我同意您必须首先使用
$elemMatch
来查找正确的匹配项(否则,
$lt
/
$gt
标准将在任何数组索引上匹配),但这并不能避免您返回整个文档,这是OP的问题。$elemMatch进行投影。我明白了,有两种不同的
$elemMatch
:查询运算符和投影运算符,后者更新了很多。对于OP的场景,他还必须使用
$elemMatch
查询操作符。