所以我对MongoDB很新。这是一个虚构的数据库,格式如下。
{
"_id": "message_id",
"headers": {
"from": <from_email>,
"to": <to_email>,
"timestamp": <timestamp>
},
"message": {
"message": <the message contents>,
"signature": <signature contents>
}
}
假设收到的所有电子邮件都插入其中,有时会发送电子邮件。如何在没有任何双重发送的情况下从作者返回电子邮件集合。
我认为这可能会这样做,但它似乎没有按预期工作:
db.mycoll.find({"headers.from": <authorname>}).distinct("message.message")
编辑: 请原谅,似乎我一直在制作某种拼写错误,上面的查询有效,但它只返回messages.messages而没有Headers,我如何保持标题完好无损?
答案 0 :(得分:1)
很难从您的问题中确定哪个部分是“重复”,因此应该是唯一的。虽然诸如消息“_id”和“timestamp”之类的东西不会重复,但是这只是真正留下了消息内容,并且该消息可能会“脱离”同一个人。< / p>
文档重塑通常最好由aggregation framework处理:
db.collection.aggregate([
{ "$group": {
"_id": { "message": "$message.message", "from": "$headers.from" },
"message_id": { "$first": "$_id" },
"headers": { "$first": "$headers" },
"message": { "$first": "$message" }
}},
{ "$project": {
"_id": "$message_id",
"headers": 1,
"message": 1
}}
])
$group
将使用$first
操作过滤掉任何匹配的邮件内容,只选择文档分组边界上匹配字段的“第一个”找到的项目。
此处假设现有订单是“timestamp”,但如果没有,那么您可能希望将$sort
作为第一个管道阶段应用于其他管道阶段:
{ "$sort": { "headers.timestamp": 1 } }
最终$project
实际上只是恢复了原始文档表单,并删除了之前提供的“分组键”。比复制信息和/或放置不合适的东西更漂亮。
答案 1 :(得分:0)
您可以使用distinct()
从特定作者返回一系列不同的消息,如下所示:
db.collection.distinct('message.message', {"headers.from": <authorname>})
答案 2 :(得分:0)
您目前尚未实施的内容(至少据我所知)。一个解决方法是this
答案 3 :(得分:0)
db.mycoll.aggregate([
{
$match:{"headers.from": <authorname>}
},{
$group:{
_id:"$headers.from",
"message":{$addToSet:"$message.message"}
}
}
])
答案 4 :(得分:0)
以Neil Lunn的答案为基础: 我认为可以做到
db.collection.aggregate([{"$match": {"headers.from": <from email>} } ,
{"$group": { "_id": "$message.message"},
"headers": {"$first": "$headers"},
"signature": {"$first": "$message.signature"},
"message_id": "$_id" }},
{"$project" : { "_id": "$message_id",
"headers": "$headers",
"message": { "message": "$_id", "signature": "$signature" } } }])
由于_id
必须是唯一的,因此重复的消息不会生成列表,然后$project
会将其重组为具有正确键名的原始对象结构。
我想我在这方面只有一个问题 - 有没有办法强制唯一性而不会聚合到_id
中,或者这通常被认为是在MongoDB
中执行此操作的正确方法吗?