如何在ObjectId上执行操作作为查询的一部分?

时间:2013-12-16 14:20:27

标签: mongodb

我有一个带有数字ID的集合,我想导出和处理它。

我有一个Python脚本,它接收一个JSON文档并对其进行转换,因此我可以运行一个以mongoexport开头的Unix管道,并将其输出管道输入Python,如下所示:

mongoexport --host myhost --db mydb --collection mycol  | python ./transform.py

但是这个操作很长(一切都在一个线程中处理)所以我找到了一种并行化的方法。我将我的(数字)id分成8个块(使用id mod 8)并且并行运行8个进程:

for var in {0..7} 
do
    mongoexport --host myhost --db mydb --collection mycol --query '{ id: { $mod: [8, '$var']} }' | python ./transform.py &
done

这将我的集合分成8个不相交的部分,这些部分一起覆盖了我的所有集合。

我拥有的另一个集合有一个默认的ObjectId,我想要执行以下操作:

for var in {0..7} 
do
    mongoexport --host myhost --db mydb --collection mycol --query '{ _id: { $mod: [8, '$var']} }' | python ./transform.py &
done

但是,在这种情况下,ObjectId不支持模运算。

如何使用ObjectId将我的集合分成不相交的分数?

1 个答案:

答案 0 :(得分:0)

您需要使用Python来驱动脚本,而不是bash。一个ObjectId的first four bytes are the time it was created。因此,请尝试查询集合中的第一个和最后一个_id,并将其划分为八个相等持续时间的范围。在Python中:

min_id = db.collection.find().sort([('_id', 1)]).limit(1)[0]['_id']
start = min_id.generation_time
print start
max_id = db.collection.find().sort([('_id', -1)]).limit(1)[0]['_id']
print max_id.generation_time
delta = max_id.generation_time - min_id.generation_time
step = delta / 8
print step

然后,为每个范围启动一个线程:

import threading, functools

threads = []
for i in range(8):
    thread = threading.Thread(target=functools.partial(my_function, start))
    thread.start()
    threads.append(thread)
    start += step

for thread in threads:
    thread.join()

my_function中,您应该查询所有_ids> = start和<开始+步骤:

collection.find({'_id': {'$gte': start, '$lt': start + step}})