Python札记--MongoDB模糊查询

王朝学院·作者佚名  2016-08-27
窄屏简体版  字體: 小  |  中  |  大  |  超大  

最近在使用MongoDB的时候,遇到了使用多个关键词进行模糊查询的场景。竹风使用的是mongoengine库。

查了各种资料,最后总结出比较好用的方法。先上代码,后面进行详细说明。如下:

1#!/usr/bin/env python2#coding:utf-834importre5importmongoengine6frommongoengineimport*78mongoengine.register_connection('default','test', host='127.0.0.1')910classTestData(Document):11name =StringField()12content =StringField()1314TestData.objects.get_or_create(name='天地玄黄',defaults={'content':'abc123'})15TestData.objects.get_or_create(name='宇宙洪荒',defaults={'content':'ABC123'})16TestData.objects.get_or_create(name='天天向上',defaults={'content':'Abc123'})1718defPRint_arr(obj):19printobj.name,obj.content2021deffuzzy_query_by_contains():22print"\n###使用mongoengine的contains进行查询"23print"#contains区分大小写:"24test_data_list = TestData.objects(content__contains='abc123')25map(print_arr,test_data_list)2627print"#icontains不区分大小写:"28test_data_list = TestData.objects(content__icontains='abc123')29map(print_arr,test_data_list)3031deffuzzy_query_by_Q():32print"\n###使用Q来进行查询"33test_data_list =TestData.objects(34Q(name__icontains=u'天地') | Q(name__icontains=u'宇宙'))35map(print_arr,test_data_list)3637deffuzzy_query_by_pymongo():38print"\n###使用raw queries,New in version 0.4"39print"#单个查询条件"40search ={41'__raw__':{42'content':{'$regex':'A\S+\d+'},43},44}45test_data_list = TestData.objects(**search)46map(print_arr,test_data_list)4748print"#多个查询条件"49search ={50'__raw__':{51'name':{'$in':[re.compile(u'天天'),re.compile(u'宇宙')]},52},53}54test_data_list = TestData.objects(**search)55map(print_arr,test_data_list)5657if__name__=='__main__':58fuzzy_query_by_contains()59fuzzy_query_by_Q()60fuzzy_query_by_pymongo()

先讨论一下fuzzy_query_by_contains方法,这里用的是mongoengine提供的contains操作。值得注意的是,contains区分大小写,而icontains不区分大小写。这种方式在针对一个关键词进行模糊查询的时候特别方便。

然后是fuzzy_query_by_Q方法,这里结合了contains和Q来进行组合查询。当使用Q()来进行组合查询时,必须使用位运算符(|和&),而不能使用or,and来进行逻辑运算。这种方式比较合适确定关键词数目的情况。如果关键词的数目是不定的,这种方式就略显纠结了。

竹风在动态关键词模糊查询的问题也是纠结良久,差点就要对每个关键词分别查询,然后取交集凑结果了。后来在文档中发现,mongoengine有__raw__这个参数,可以执行PyMongo的查询(version 0.4提供的新功能)。于是几经试验,fuzzy_query_by_pymongo方法就出炉了。

PyMongo支持正则表达式,提供了两种方法,一种是使用$regex,另一种是使用re.compile()。

在例子中,对单个关键词进行模糊查询,对应的代码为:{'$regex':'A\S+\d+'}

接着就是对多个关键词进行查询,对应的代码为:{'$in':[re.compile(u'天天'),re.compile(u'宇宙')]}

对代码进行一些修改,以便接受多个关键词,代码如下:

1deffuzzy_query_by_pymongo():2print"#多个查询条件"3keyWord= u'天天 宇宙'4search = {'__raw__': {'name':{'$in':map(re.compile,keyword.split())}}}5test_data_list = TestData.objects(**search)6map(print_arr,test_data_list)

顺带一提,例子中创建数据是用的get_or_create,会返回一个元组,第一个元素是创建or查询的对象,第二个元素是是否创建成功。文档中的推荐用法如下:

1>>> a, created = User.objects.get_or_create(name='User A', defaults={'age':30})2>>> b, created = User.objects.get_or_create(name='User A', defaults={'age':40})3>>> a.name == b.name and a.age ==b.age4True

最后是例子运行的结果,返回的结果顺序可能略有不同,不必在意。

1$ python mongodb_test.py23###使用mongoengine的contains进行查询4#contains区分大小写:5天地玄黄 abc1236#icontains不区分大小写:7天地玄黄 abc1238宇宙洪荒 ABC1239天天向上 Abc1231011###使用Q来进行查询12天地玄黄 abc12313宇宙洪荒 ABC1231415###使用raw queries,Newinversion0.416#单个查询条件17宇宙洪荒 ABC12318天天向上 Abc12319#多个查询条件20宇宙洪荒 ABC12321天天向上 Abc123

 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
© 2005- 王朝網路 版權所有 導航