我有一组推文,我试图在根级别(类似于引用的推文)输出转发到新的集合,以便稍后使用转储和恢复将它们与原始集合合并。 转发状态是推文文档中的子文档,可能有多条推文转发同一条推文。 如何在根级别进行转发并添加一个名为'转发_by'包含转发它的所有推文的ID?
请记住,我使用tweet id作为主索引(_id),以避免在组合(mongorestore)集合时创建重复项。
我的收藏品有以下形式:
{
"_id" : "123456",
"other_fields1" : "values1",
"retweeted_status" : {
"retweet_id": "159753",
"other_fields2" : "values2",
}
}
理想的输出预计如下:
{
"_id" : "159753",
"other_fields2" : "values2",
"retweeted_by" : [ "123456", "974631", "121212"]
}
编辑以澄清:
子文档中的字段(other_fields2)是多个字段(~28),这些字段并不存在于其他推文中
答案 0 :(得分:0)
好的..所以我终于找到了我的问题的解决方案..我不确定这是否是最好的方法:
db.tweets.aggregate([
{
$match: { retweeted_status: {$exists: true}}
},
{
$addFields: { 'retweeted_status.retweeted_by' : '$_id', 'retweeted_status._id' : '$retweeted_status.id_str'}
},
{
$replaceRoot: { newRoot: '$retweeted_status'}
},
{
$group: { _id: '$_id', doc: { '$first': '$$ROOT' }, retweeted_by: {$addToSet: '$retweeted_by'}}
},
{
$addFields: { 'doc.retweeted_by' : '$retweeted_by'}
},
{
$replaceRoot: { newRoot: '$doc'}
},
{
$project: { id: 0 , id_str: 0 }
},
{
$out: 'retweets'
}
], {allowDiskUse: true})
最初,每个文件(推文)都有以下形式:
{parent,{subdocument}}
首先匹配retweeted_status(子文档)的存在,然后在通过retweeted_status id进行分组之前,我添加了一个带有父推文id的字段:
{parent,{subdocument,parent_id}}
然后用修改后的子文档替换了root:
{subdocument,parent_id}
然后,我按新根的_id分组,获取该组的第一个文档,并添加了一个新的累加器集(retweeted_by)。 (不是$ push,因为twitter API有时会发送重复项)
到目前为止,根文档包含_id,嵌入在字段'doc'中的转发文档,以及包含父项的数组:
{doc {subdocument,parent_id},[parent_ids]}
接下来,我将parents数组添加为doc中的一个字段,(覆盖之前添加的retweeted_by字段):
{doc {subdocument,[parent_ids]},[parent_ids]}
然后用新文档替换父(root)。然后排除包含与_id相同数字的字段:
{subdocument,[parent_ids]}