我正在开发一个MongoDB项目,该项目存储推文并由其他人创建。
这个人决定在MongoDB中使用Twitter推文ID作为_id
字段,这意味着我现在无法确定性地对推文进行排序。
示例:
> db.tweets.find().sort({_id : 1}).limit(4)
{'message' : '...', 'userId' : NumberLong(123), '_id' : NumberLong(1)}
{'message' : '...', 'userId' : NumberLong(123), '_id' : NumberLong(2)}
{'message' : '...', 'userId' : NumberLong(123), '_id' : NumberLong(3)}
{'message' : '...', 'userId' : NumberLong(123), '_id' : NumberLong(5)}
对字段ID进行排序的原因是非确定性的,在以后,我的系统可以将ID为4的现有推文添加到数据库中,这意味着相同的命令会给出不同的结果集:
> db.tweets.find().sort({_id : 1}).limit(4)
{'message' : '...', 'userId' : NumberLong(123), '_id' : NumberLong(1)}
{'message' : '...', 'userId' : NumberLong(123), '_id' : NumberLong(2)}
{'message' : '...', 'userId' : NumberLong(123), '_id' : NumberLong(3)}
{'message' : '...', 'userId' : NumberLong(123), '_id' : NumberLong(4)}
我的问题是:有没有办法添加新的'字段'对于集合中的每个条目,其值为ObjectID
,以便我可以对其进行排序?
或者,如果没有,建议将用于重命名' _id
字段说出tweetId
,然后创建_id
类型的ObjectID
字段
由于
答案 0 :(得分:1)
实际更改_id
字段的唯一方法是复制文档,更改_id
,然后删除旧文档,如以下答案所述:
How update the _id of one MongoDB Document?
要简单地添加一个新字段,将更新函数传递给游标的forEach
函数应该有效:
db.tweets.find().forEach(
function (tweet) {
db.tweets.update({_id: tweet._id}, {$set: {newFieldName: tweet._id}});
}
);
答案 1 :(得分:0)
Shawn链接的帖子中的一些片段有几个缺陷。虽然这个想法是正确的,但使用命令行mongo
可能会导致一些问题。
在mongo
中很难在添加任何新推文之前获取所有推文的“快照”。我能找到的唯一方法是使用:
$ db.tweets.find({}, {_id : 1}).toArray()
或者
$ db.tweets.distinct('_id')
不幸的是,由于我的数据库中有超过200万条推文,导致mongo
内存不足。我有一个"exception: distinct too big, 16mb cap"
错误,
相反,我使用了Python,这是脚本:
#!/usr/bin/env python
"""A tool to work through all tweets, and convert the '_id'
from the Tweet ID into an ObjectID (saving the tweet)
ID in the 'tweetID' field
"""
import pymongo
from bson.objectid import ObjectId
if __name__ == "__main__":
client = pymongo.MongoClient()
db = client.guaiamum
ids = list(t['_id'] for t in db.tweets.find({'_id': {'$type' : 18}}, {'_id' : 1}))
for _id in ids:
tweet = db.tweets.find_one({'_id' : _id})
tweet['_id'] = ObjectId()
tweet['twitterId'] = _id
db.tweets.insert(tweet)
db.tweets.remove(_id, multi=False)
运行仍需要1.5小时,但奇怪的是,它仍然比使用mongo