确定性地对 MongoDB 集合进行排序(添加新的 ObjectID 字段)
Sorting MongoDB collection deterministically (add new ObjectID field)
我正在开发一个 MongoDB 项目,该项目存储推文并由其他人创建。
此人决定将 Twitter 推文 ID 用于 MongoDB 中的 _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)}
我的问题是:有没有办法向集合中的每个条目添加一个新的 'field',值类型为 ObjectID
,以便我可以对其进行排序?
或者,如果不是,建议 'renaming' _id
字段说 tweetId
然后使 _id
字段类型为 ObjectID
谢谢
实际更改 _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}});
}
);
Shawn 链接到的 post 中的一些片段有几个缺陷。虽然这个想法是正确的,但使用命令行 mongo
可能会导致一些问题。
在 mongo
中很难在添加任何新推文之前获取所有推文的 'snapshot'。我能找到的唯一方法是使用:
$ 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
快得多
我正在开发一个 MongoDB 项目,该项目存储推文并由其他人创建。
此人决定将 Twitter 推文 ID 用于 MongoDB 中的 _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)}
我的问题是:有没有办法向集合中的每个条目添加一个新的 'field',值类型为 ObjectID
,以便我可以对其进行排序?
或者,如果不是,建议 'renaming' _id
字段说 tweetId
然后使 _id
字段类型为 ObjectID
谢谢
实际更改 _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}});
}
);
Shawn 链接到的 post 中的一些片段有几个缺陷。虽然这个想法是正确的,但使用命令行 mongo
可能会导致一些问题。
在 mongo
中很难在添加任何新推文之前获取所有推文的 'snapshot'。我能找到的唯一方法是使用:
$ 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