如何在MongoDB中创建find()
,使用find为> =有一些值,但该值是一个数字字符串?
如果我运行以下行(在MongoDB数据库中搜索高于1的模式):
cursor = db.foo.find({"mode": {"$gt": 1}})
仅当MongoDB中的数据采用以下格式时才会起作用:
data = {"mode":3}
但我需要将find()
与此数据一起使用:
data = {"mode":'3'} # as string
我该怎么做?
以下是我的例子:
from pymongo import MongoClient
client = MongoClient()
db = client.test
db.foo.drop()
data = {"mode":3} # Works because this is a numeric
data = {"mode":'3'} # Won't work!!!!!!!!!! But my database contains only numeric strings...how can use like this?
db.foo.insert_one(data)
print(db.foo.count())
cursor = db.foo.find({"mode": {"$gt": 1}})
for document in cursor:
print(document)
答案 0 :(得分:2)
如果您将数字数据存储在数据库中作为字符串,为了使用范围运算符(例如$gt
和$lt
)查询数据,您将不得不使用以下两种方法之一
首先,您可以使用JavaScript的自动转换来运行范围查询。这工作如下所示,但它非常有限,因为您不能够使用任何索引,如前面答案的注释中所述。因此,对于大数据集,这将非常慢。
db.foo.find("this.mode > 1");
第二种方法涉及正则表达式。您必须弄清楚要使用哪种正则表达式,但是一旦有了这种正则表达式,您就可以使用下面的语法来运行查询,或者使用$regex
运算符作为突出显示的here。
db.foo.find({ mode: /pattern/<options> });
除了必须弄清楚一些复杂的正则表达式之外,这种方法还有可能出现性能问题,如here所述(参见下面的摘录)。最有可能的是,您还会遇到查询没有利用索引的问题。
如果该字段存在索引,则MongoDB会将正则表达式与索引中的值进行匹配,这可能比收集扫描更快。如果正则表达式是“前缀表达式”,则可以进一步优化,这意味着所有可能的匹配都以相同的字符串开头。这允许MongoDB从该前缀构造一个“范围”,并且仅匹配该范围内的索引中的那些值。
因此,如果您经常运行这些查询,我建议您遵循第三种方法,即更改架构并将数据存储为数字。您可以使用简单的迁移脚本实现此目的,例如JavaScript中的以下内容,您可以在shell中运行。
var cursor = db.foo.find();
while (cursor.hasNext()) {
var doc = cursor.next();
var _id = doc._id;
if (doc.mode) {
var modeString = doc.mode;
var modeInt = parseInt(modeString);
db.foo.update({ _id: _id }, { $set: { mode: modeInt } });
}
}
完成此操作后,您将能够使用$gt
和$lt
之类的运算符查询数据,对其进行排序,并轻松利用索引。
答案 1 :(得分:1)
来自Mongo docs,
$ type选择字段值为指定BSON类型实例的文档。在处理数据类型不可预测的高度非结构化数据时,按数据类型查询非常有用。 {field:{$ type:BSON type number | String alias}}
$ type返回字段的BSON类型与传递给$ type的BSON类型匹配的文档。
我猜你必须在你的情况下明确传递$ type,这可能是:
data = {{"mode":{$type:"string"}}:'3'}
答案 2 :(得分:0)