MongoDB 和 rmongodb。获取查找的大小而不是返回所有结果
MongoDB and rmongodb. Get size of find instead of returning all results
我有一个 MongoDB 集合,其中包含超过 100k 个文档(这个数字会继续增长)。每个文档都有几个字段是单个值,大约 50 个字段,每个字段都是长度为 1000 的数组。我正在使用 rmongodb 在 R 中分析结果。
在 rmongodb 中,我使用 mongo.find.all()
,查询设置为要搜索的某些条件组合,字段设置为 return 字段的子集。 mongo shell 中的等效项类似于:
db.collection.find({query1 : "value1", query2 : "value2"},{field1 : 1, field2 : 1, field3 : 1})
这个 return 是一个 data.frame 的结果,我对其进行了一些 post 处理并以 data.table 结束。
我想做的是为查询添加一些保护措施。如果查询范围很广,并且 returned 的字段是许多较大的数组字段,则结果 data.table 可能会达到数十 GB。这可能是预期的,但我想添加一些标志或错误检查,这样就不会有人不小心尝试一次 return 数百 GB。
我知道我可以获得与查询匹配的文档数(mongo.count
in rmongodb,db.collection.find({...},{...}).count()
in the shell)。我还可以获得平均文档大小 (db.collection.stats().avgObjSize
)。
我不知道该怎么做,也不知道是否可能,是在实际 returned 之前获取查找的大小(以 MB 为单位,而不是数字)。由于我经常 return 只处理字段的一个子集,因此 count 和 avgObjSize 无法非常准确地估计结果 data.table 的大小。大小需要同时考虑查询和字段。
是否有像 db.collection.find({},{}).sizeOf()
这样的命令可以 return 我的查找(查询,字段)的大小(以 MB 为单位)?我能看到的唯一选项是 count()
和 size()
两者都是 return 文件数量。
您可以针对这种情况所需的灵活性编写脚本:
(我假设你想要 return 最大 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)
您可以手动遍历游标(就像在 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::rbindlist()
转换成data.table
。
我有一个 MongoDB 集合,其中包含超过 100k 个文档(这个数字会继续增长)。每个文档都有几个字段是单个值,大约 50 个字段,每个字段都是长度为 1000 的数组。我正在使用 rmongodb 在 R 中分析结果。
在 rmongodb 中,我使用 mongo.find.all()
,查询设置为要搜索的某些条件组合,字段设置为 return 字段的子集。 mongo shell 中的等效项类似于:
db.collection.find({query1 : "value1", query2 : "value2"},{field1 : 1, field2 : 1, field3 : 1})
这个 return 是一个 data.frame 的结果,我对其进行了一些 post 处理并以 data.table 结束。
我想做的是为查询添加一些保护措施。如果查询范围很广,并且 returned 的字段是许多较大的数组字段,则结果 data.table 可能会达到数十 GB。这可能是预期的,但我想添加一些标志或错误检查,这样就不会有人不小心尝试一次 return 数百 GB。
我知道我可以获得与查询匹配的文档数(mongo.count
in rmongodb,db.collection.find({...},{...}).count()
in the shell)。我还可以获得平均文档大小 (db.collection.stats().avgObjSize
)。
我不知道该怎么做,也不知道是否可能,是在实际 returned 之前获取查找的大小(以 MB 为单位,而不是数字)。由于我经常 return 只处理字段的一个子集,因此 count 和 avgObjSize 无法非常准确地估计结果 data.table 的大小。大小需要同时考虑查询和字段。
是否有像 db.collection.find({},{}).sizeOf()
这样的命令可以 return 我的查找(查询,字段)的大小(以 MB 为单位)?我能看到的唯一选项是 count()
和 size()
两者都是 return 文件数量。
您可以针对这种情况所需的灵活性编写脚本: (我假设你想要 return 最大 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)
您可以手动遍历游标(就像在 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::rbindlist()
转换成data.table
。