我有一个带有> 100k文档的MongoDB集合(这个数字会继续增长)。每个文档都有一些单个值的字段,以及大约50个字段,每个字段都是长度为1000的数组。我正在使用rmongodb分析R中的结果。
在rmongodb中,我使用mongo.find.all()
将查询设置为要搜索的某些条件组合,并将字段设置为要返回的字段的子集。 mongo shell中的等价物将类似于:
db.collection.find({query1 : "value1", query2 : "value2"},{field1 : 1, field2 : 1, field3 : 1})
这将返回结果的data.frame,我会对其进行一些后处理并最终得到data.table。
我想要做的是为查询添加一些保护措施。如果查询是宽泛的,并且返回的字段是许多较大的数组字段,则生成的data.table可以是几十GB。这可能是预期的,但我想添加一些标记或错误检查,以便有人不会意外地尝试一次返回数百GB。
我知道我可以计算与查询匹配的文档数量(在{rmongodb中为mongo.count
,在shell中为db.collection.find({...},{...}).count()
)。我还可以获得平均文档大小(db.collection.stats().avgObjSize
)。
我不知道怎么做,也不知道是否可能,是在实际返回查找之前获取查找的大小(以MB为单位,而不是数字)。由于我经常只返回字段的一个子集,因此count和avgObjSize不能非常准确地估计得到的data.table的大小。大小需要考虑查询和字段。
是否有像db.collection.find({},{}).sizeOf()
这样的命令会返回我的查找(查询,字段)的MB大小?我能看到的唯一选项是count()
和size()
,这两个选项都会返回文档数量。
答案 0 :(得分:1)
您可以手动迭代游标(就像在mongo.cursor.to.list中一样)并迭代检查结果对象的大小。像这样:
LIMIT = 1024 * 1024 * 1024
res_size = 0
mongo.cursor.to.list_with_check <- function (cursor,
keep.ordering = TRUE,
limit = LIMIT) {
# make environment to avoid extra copies
e <- new.env(parent = emptyenv())
i <- 1
while (mongo.cursor.next(cursor) && res_size < limit) {
val = mongo.bson.to.list(mongo.cursor.value(cursor))
res_size = res_size + object.size(val)
assign(x = as.character(i),
value = val, envir = e)
i <- i + 1
}
# convert back to list
res <- as.list(e)
if (isTRUE(keep.ordering)) setNames(res[order(as.integer(names(res)))], NULL)
else setNames(res, NULL)
}
之后,您可以通过data.table
将其转换为data.table::rbindlist()
。
答案 1 :(得分:0)
您可以编写脚本以满足此情况下所需的灵活性: (我假设你想要最多返回1GB)
//limit 1GB
var mbLimit = 1024*1024;
//find number to show and round it to an int
var numberShow = (mbLimit/db.restaurants.stats().avrObjSize) | 0;
//limit the query
db.restaurants.find({
{query1 : "value1", query2 : "value2"},{field1 : 1, field2 : 1, field3 : 1}
}).limit(numberShow)