蒙古指数。如何索引嵌套在数组中的文档上的单个对象

时间:2014-02-27 20:39:32

标签: mongodb indexing mongodb-query aggregation-framework

我有以下文件:

{
    'date': date,
    '_id': ObjectId,
    'Log': [
        {
            'lat': float,
            'lng': float,
            'date': float,
            'speed': float,
            'heading': float,
            'fix': float
        }
    ]
}

对于1个文档,Log数组可以是几百个条目。

我需要在每个文档中查询date第一个最后一个 Log元素。 我知道如何查询它,但我需要快速完成,所以我想建立一个的索引。我不想索引Log.date,因为它太大了......我怎么能索引它们?

2 个答案:

答案 0 :(得分:1)

事实上,在不知道如何处理文档的情况下很难提供建议。其中一个解决方案可能是使用稀疏索引。您只需要为每个第一个和最后一个数组元素添加一个新字段,我们称之为shouldIndex。然后,只需创建一个包含shouldIndexdate字段的稀疏索引。这是一个简短的例子:

假设我们有这个文件

{"Log": 
    [{'lat': 1, 'lng': 2, 'date': new Date(), shouldIndex : true}, 
    {'lat': 3, 'lng': 4, 'date': new Date()}, 
    {'lat': 5, 'lng': 6, 'date': new Date()}, 
    {'lat': 7, 'lng': 8, 'date': new Date(), shouldIndex : true}]}

请注意第一个元素和最后一个元素包含shouldIndex字段。

db.testSparseIndex.ensureIndex( { "Log.shouldIndex": 1, "Log.date":1 }, { spar
se: true } )

此索引应仅包含您的第一个和最后一个元素的条目。

或者,您可以将第一个和最后一个元素日期字段存储在单独的数组中。

有关稀疏索引的更多信息,请参阅此article

希望它有所帮助!

答案 1 :(得分:1)

所以有一个关于索引的答案从根本上是正确的。截至撰写时,似乎有点不清楚你是否在谈论索引。您似乎想要做的就是获取 第一个最后日期来自数组中的元素。

考虑到这一点,有几种方法:

<强> 1 即可。 数组中的元素已自然插入日期值增加

因此,如果完成对此字段的所有写入的方式,只需在一段时间内使用$push运算符,并且从不更新这些项目,至少在更改日期方面,您的商品已经按顺序排列。

这意味着您只需从数组中获取第一个和最后一个元素

db.collection.find({ _id: id },{ Log: {$slice: 1 }});    // gets the first element
db.collection.find({ _id: id },{ Log: {$slice: -1 }});   // gets the last element

现在当然这是两个查询,但这是一个相对简单的操作,而且成本不高。

<强> 2 即可。 由于某种原因,您的元素不是按日期自然排序

如果是这种情况,或者确实如果您不能使用这两个查询表单,那么您可以在aggregation中获取第一个和最后一个值,但使用$min和{{ 3}}修饰符

db.collection.aggregate([

    // You might want to match first. Just doing one _id here. (commented)
    //{"$match": { "_id": id }},

    //Unwind the array
    {"$unwind": "$Log" },

    //
    {"$group": { 
        "_id": "$_id",
        "firstDate": {"$min": "$Log.Date" },
        "lastDate": {"$max": "$Log.Date" }
    }}

])

最后,如果您的用例是获取具有第一个和最后一个日期的文档的详细信息,我们也可以这样做,稍微镜像最初的两个查询表单。使用$max$first

db.collection.aggregate([

    // You might want to match first. Just doing one _id here. (commented)
    //{"$match": { "_id": id }},

    //Unwind the array
    {"$unwind": "$Log" },

    // Sort the results on the date
    {"$sort": { "_id._id": 1, "Log.date": 1 }},

    // Group using $first and $last
    {"$group": { 
        "_id": "$_id",
        "firstLog": {"$first": "$Log" },
        "lastLog": {"$last": "$Log" }
    }}

])

您的里程可能会有所不同,但如果这确实是该索引的唯一用途,那么这些方法可能无需索引。