快速统计bson文档中的对象个数
Quickly count the number of objects in bson document
我想计算存储在 mongodb bson 文件中的文档数量,而不必通过 mongo 恢复将文件导入数据库。
我能想到的最好的 python 是
bson_doc = open('./archive.bson','rb')
it = bson.decode_file_iter(bson_doc)
total = sum(1 for _ in it)
print(total)
这在理论上可行,但在 bson 文档很大时在实践中会很慢。谁有更快的方法来计算 bson 文档中的文档数量而无需进行完整解码?
我目前正在使用 python 2.7 和 pymongo。
https://api.mongodb.com/python/current/api/bson/index.html
我手边没有可供尝试的文件,但我相信有办法 - 如果您手动解析数据。
source for bson.decode_file_iter
(没有文档字符串)是这样的:
_UNPACK_INT = struct.Struct("<i").unpack
def decode_file_iter(file_obj, codec_options=DEFAULT_CODEC_OPTIONS):
while True:
# Read size of next object.
size_data = file_obj.read(4)
if len(size_data) == 0:
break # Finished with file normaly.
elif len(size_data) != 4:
raise InvalidBSON("cut off in middle of objsize")
obj_size = _UNPACK_INT(size_data)[0] - 4
elements = size_data + file_obj.read(obj_size)
yield _bson_to_dict(elements, codec_options)
我想,耗时的操作是 _bson_to_dict
调用 - 而您不需要。
因此,您只需读取文件 - 获取具有下一个文档大小的 int32 值并跳过它。然后计算您遇到了多少文档。
所以,我相信这个函数应该可以解决问题:
import struct
import os
from bson.errors import InvalidBSON
def count_file_documents(file_obj):
"""Counts how many documents provided BSON file contains"""
cnt = 0
while True:
# Read size of next object.
size_data = file_obj.read(4)
if len(size_data) == 0:
break # Finished with file normaly.
elif len(size_data) != 4:
raise InvalidBSON("cut off in middle of objsize")
obj_size = struct.Struct("<i").unpack(size_data)[0] - 4
# Skip the next obj_size bytes
file_obj.seek(obj_size, os.SEEK_CUR)
cnt += 1
return cnt
(不过我还没有测试代码。手头没有 MongoDB。)
我想计算存储在 mongodb bson 文件中的文档数量,而不必通过 mongo 恢复将文件导入数据库。
我能想到的最好的 python 是
bson_doc = open('./archive.bson','rb')
it = bson.decode_file_iter(bson_doc)
total = sum(1 for _ in it)
print(total)
这在理论上可行,但在 bson 文档很大时在实践中会很慢。谁有更快的方法来计算 bson 文档中的文档数量而无需进行完整解码?
我目前正在使用 python 2.7 和 pymongo。 https://api.mongodb.com/python/current/api/bson/index.html
我手边没有可供尝试的文件,但我相信有办法 - 如果您手动解析数据。
source for bson.decode_file_iter
(没有文档字符串)是这样的:
_UNPACK_INT = struct.Struct("<i").unpack
def decode_file_iter(file_obj, codec_options=DEFAULT_CODEC_OPTIONS):
while True:
# Read size of next object.
size_data = file_obj.read(4)
if len(size_data) == 0:
break # Finished with file normaly.
elif len(size_data) != 4:
raise InvalidBSON("cut off in middle of objsize")
obj_size = _UNPACK_INT(size_data)[0] - 4
elements = size_data + file_obj.read(obj_size)
yield _bson_to_dict(elements, codec_options)
我想,耗时的操作是 _bson_to_dict
调用 - 而您不需要。
因此,您只需读取文件 - 获取具有下一个文档大小的 int32 值并跳过它。然后计算您遇到了多少文档。
所以,我相信这个函数应该可以解决问题:
import struct
import os
from bson.errors import InvalidBSON
def count_file_documents(file_obj):
"""Counts how many documents provided BSON file contains"""
cnt = 0
while True:
# Read size of next object.
size_data = file_obj.read(4)
if len(size_data) == 0:
break # Finished with file normaly.
elif len(size_data) != 4:
raise InvalidBSON("cut off in middle of objsize")
obj_size = struct.Struct("<i").unpack(size_data)[0] - 4
# Skip the next obj_size bytes
file_obj.seek(obj_size, os.SEEK_CUR)
cnt += 1
return cnt
(不过我还没有测试代码。手头没有 MongoDB。)