我有一个带有数字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将我的集合分成不相交的分数?
答案 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}})