MongoDB - 查找最接近整数值的文档

17

假设我有一个包含文档的集合,其中有一个比率属性是浮点数。

{'ratio':1.437}

如何编写查询以查找最接近给定整数的单个文档,而不使用驱动程序将它们全部加载到内存中,并找到具有 abs(x-ratio) 最小值的一个?

2个回答

34

有趣的问题。我不知道你是否可以在一个查询中完成,但你可以分成两个查询来完成:

var x = 1; // given integer
closestBelow = db.test.find({ratio: {$lte: x}}).sort({ratio: -1}).limit(1);
closestAbove = db.test.find({ratio: {$gt: x}}).sort({ratio: 1}).limit(1);

然后您只需检查这两个文档中哪一个的ratio最接近目标整数。

MongoDB 3.2 更新

3.2版本添加了对$abs绝对值聚合运算符的支持,现在可以通过单个aggregate查询来完成此操作:

var x = 1;
db.test.aggregate([
    // Project a diff field that's the absolute difference along with the original doc.
    {$project: {diff: {$abs: {$subtract: [x, '$ratio']}}, doc: '$$ROOT'}},
    // Order the docs by diff
    {$sort: {diff: 1}},
    // Take the first one
    {$limit: 1}
])

1
这种聚合方法对于日期时间也适用良好,其区别在于所需时间点与数据集中最近时间点之间的毫秒差。 - Daniel F
这种聚合方式是否足够智能,可以有效地使用索引来处理“比率”?我怀疑对于更大的集合,使用两个数据库请求的第一种解决方案可能会更快。 - warvariuc
我正在做类似的事情,但有5个参数。我想找到最佳匹配的文档来查询这些值:{'a': 1.1,'b': 0.3,'c': 0.01,'d': 1.8,'e': 0.55}。我应该如何干净地完成这个任务? - Izzi

7

我有另一个想法,但非常棘手,需要改变您的数据结构。

您可以使用mongodb支持的地理位置索引

首先,将您的数据更改为以下结构,并将第二个值保留为0

{'ratio':[1.437, 0]}

然后你可以使用$near运算符来查找最接近的比率值,并且由于该运算符返回按距离排序的列表与您给定的整数,所以您必须使用limit来仅获取最接近的值。

db.places.find( { ratio : { $near : [50,0] } } ).limit(1)

如果您不想这样做,我认为您可以使用@JohnnyHK的答案 :)

我曾考虑过以这种方式应用地理定位...我想我会试一试。比率值实际上是图像的宽高比,所以我可以将宽度x高度视为一个维度查询。 - DeaconDesperado
我正在考虑类似的事情。你用这种方法有什么好运气吗? - Izzi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接