MongoDB查询断开关系并删除重复项

时间:2013-11-19 20:07:14

标签: mongodb mongodb-query

我有包含Version,URL和DateAdded字段的文档(除其他外,但这些是相关的)。

我想查找版本为“5.5”且DateAdded小于或等于2013年1月1日的所有文档。这非常简单,但我还想要以下行为:

如果两个或多个文档具有相同的URL,则仅返回具有最新DateAdded的文档(再次提供,即小于或等于2013年1月1日)。如果所有这些都可以在一个查询中表达,那将会很棒(但我主要关心的是性能)。

我一直在我的客户端代码中进行最后一点过滤(在MongoDB之外),但这最终效率低下,更不用说不优雅了。

我也尝试使用Mongo的MapReduce功能来完成同样的事情,但这非常慢,因为它似乎将我的大部分集合复制到另一个集合。

是否有高效的解决方案?

1 个答案:

答案 0 :(得分:1)

这应该可以解决问题。

示例数据:

db.foo.insert({ "_id" : ObjectId("528bd5bded29286a62959513"), "Version" : "5.3", "URL" : "foo.bar.com/asdfwoaef", "DateAdded" : ISODate("2012-10-05T00:00:00Z") })
db.foo.insert({ "_id" : ObjectId("528bd5e8ed29286a62959514"), "Version" : "5.6", "URL" : "foo.bar.com/asdfwoaef", "DateAdded" : ISODate("2012-12-05T00:00:00Z") })
db.foo.insert({ "_id" : ObjectId("528bd621ed29286a62959515"), "Version" : "5.5", "URL" : "foo.bar.com/aafoobbb", "DateAdded" : ISODate("2012-11-04T00:00:00Z") })
db.foo.insert({ "_id" : ObjectId("528bd629ed29286a62959516"), "Version" : "5.5", "URL" : "foo.bar.com/aafoobbb", "DateAdded" : ISODate("2012-11-05T00:00:00Z") })
db.foo.insert({ "_id" : ObjectId("528bd642ed29286a62959517"), "Version" : "5.5", "URL" : "foo.bar.com/aafoobbb", "DateAdded" : ISODate("2013-01-02T00:00:00Z") })
db.foo.insert({ "_id" : ObjectId("528bd744ed29286a62959518"), "Version" : "5.5", "URL" : "foo.bar.com/ccbarcc", "DateAdded" : ISODate("2013-01-02T00:00:00Z") })
db.foo.insert({ "_id" : ObjectId("528bd780ed29286a62959519"), "Version" : "5.5", "URL" : "foo.bar.com/ccbarcc", "DateAdded" : ISODate("2012-04-05T00:00:00Z") })

管道:

pipeline = [
    {
        "$match" : {
            "Version" : "5.5",
            "DateAdded" : {
                "$lt" : ISODate("2013-01-01T00:00:00Z")
            }
        }
    },
    {
        "$sort" : {
            "URL" : 1,
            "DateAdded" : -1
        }
    },
    {
        "$group" : {
            "_id" : "$URL",
            "doc" : {
                "$first" : {
                    "id" : "$_id",
                    "DateAdded" : "$DateAdded"
                }
            }
        }
    }
]

db.foo.aggregate(pipeline)

结果如下:

{
    "result" : [
        {
            "_id" : "foo.bar.com/ccbarcc",
            "doc" : {
                "id" : ObjectId("528bd780ed29286a62959519"),
                "DateAdded" : ISODate("2012-04-05T00:00:00Z")
            }
        },
        {
            "_id" : "foo.bar.com/aafoobbb",
            "doc" : {
                "id" : ObjectId("528bd629ed29286a62959516"),
                "DateAdded" : ISODate("2012-11-05T00:00:00Z")
            }
        }
    ],
    "ok" : 1
}