【问题标题】:How do bson arrays compare (in mongodb/pymongo)?bson 数组如何比较(在 mongodb/pymongo 中)?
【发布时间】:2012-04-25 13:37:48
【问题描述】:

我想在 mongdb 中存储一些非常大的整数,确切地说(几千个十进制数字)。这当然不适用于 BSON 支持的标准类型,考虑到我想执行范围搜索和类似的事情,我正在尝试考虑最优雅的解决方法。此要求不包括将整数存储为字符串,因为它使范围搜索变得不切实际。

我能想到的一种方法是使用标准整数的(可变长度)数组对 2^32 扩展进行编码,并向该数组添加数组本身长度的第一个条目。这样,这些数组的字典顺序对应于任意大整数的通常顺序。

例如,在一个集合中我可以有 5 个文档

{"name": "me", "fortune": [1,1000]}
{"name": "scrooge mcduck", "fortune": [11,1,0,0,0,0,0,0,0,0,0,0]}
{"name": "bruce wayne","fortune": [2, 10,0]}
{"name": "bill gates", "fortune": [2,1,1000]}
{"name": "francis", "fortune": [0]}

因此布鲁斯·韦恩的净资产是 10*2^32,比尔·盖茨的 2^32+1000 和 Scrooge McDuck 的 2^320。

然后我可以使用 {"fortune":1} 进行排序,并在我的机器上(使用 pymongo)按 francis

但是,我假设我没有在任何地方看到关于 BSON 数组比较方式的记录,并且范围搜索似乎不像我想的那样工作(例如,

find({"fortune":{$gte:[2,5,0]}}) 

不返回任何文件,但我希望得到 bruce 和 scrooge)。

谁能帮助我?谢谢

【问题讨论】:

  • 下面 Dhruv 和 Remon 描述的两种解决方案都要求我知道最大长度,并且存储大量填充零。

标签: mongodb pymongo bson


【解决方案1】:

您可以改为存储左填充字符串,表示与财富相等的精确整数。

eg.  "1000000" = 1 million
     "0010000" = 10 thousand
     "2000000" = 2 million
     "0200000" = 2 hundred thousand 

左填充零将确保这些字符串的字典比较直接对应于它们作为数值的比较。你不得不 在这里假设一个安全的最大可能财富值,比如一个 20 位数字,并且 相应地填充 0 所以一个示例文件是:

  {"name": "scrooge mcduck", "fortune": "00001100000000000000" }
  {"name": "bruce wayne",    "fortune": "00000200000000000000" }

查询:

> db.test123.find()
{ "_id" : ObjectId("4f87e142f1573cffecd0f65e"), "name" : "bruce wayne", "fortune" : "00000200000000000000" }
{ "_id" : ObjectId("4f87e150f1573cffecd0f65f"), "name" : "donald", "fortune" : "00000150000000000000" }
{ "_id" : ObjectId("4f87e160f1573cffecd0f660"), "name" : "mickey", "fortune" : "00000000000000100000" }


> db.test123.find({ "fortune" : {$gte: "00000200000000000000"}});
{ "_id" : ObjectId("4f87e142f1573cffecd0f65e"), "name" : "bruce wayne", "fortune" : "00000200000000000000" }


> db.test123.find({ "fortune" : {$lt: "00000200000000000000"}});
{ "_id" : ObjectId("4f87e150f1573cffecd0f65f"), "name" : "donald", "fortune" : "00000150000000000000" }
{ "_id" : ObjectId("4f87e160f1573cffecd0f660"), "name" : "mickey", "fortune" : "00000000000000100000" }

查询/排序将自然地工作,因为 mongodb 按字典顺序比较字符串。 但是,要对您的数据执行其他数字操作,您必须在数据处理脚本(PHP、Python、Ruby 等)中编写自定义逻辑

对于查询和数据存储,这个字符串版本应该很好。

【讨论】:

    【解决方案2】:

    很遗憾,您对数组比较的假设是不正确的。例如,查询所有小于 3 的数组值 ({array:{$lt:3}}) 的范围查询将返回至少一个元素小于 3 的所有数组,而不管元素的位置如何。因此,您的方法将行不通。

    有效但不太明显的是,将二进制 blob 用于非常大的整数,因为它们是按字节顺序比较的。这需要您为整数设置一个上限,但这应该相当简单。您可以使用 BinData(subType, base64) 表示法在 shell 中对其进行测试:

    db.col.find({fortune:{$gt:BinData(0, "e8MEnzZoFyMmD7WSHdNrFJyEk8M=")}})
    

    因此,您所要做的就是创建将大整数从(例如)字符串转换为二补码二进制的方法,然后您就设置好了。祝你好运

    【讨论】:

      猜你喜欢
      • 2015-09-27
      • 2012-02-07
      • 1970-01-01
      • 1970-01-01
      • 2014-11-26
      • 2019-07-02
      • 2016-04-03
      • 2022-09-24
      • 2021-11-26
      相关资源
      最近更新 更多