• Python札记 -- MongoDB模糊查询


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

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

     1 #!/usr/bin/env python
     2 #coding:utf-8
     3 
     4 import re
     5 import mongoengine
     6 from mongoengine import *
     7 
     8 mongoengine.register_connection('default', 'test', host='127.0.0.1')
     9 
    10 class TestData(Document):
    11     name = StringField()
    12     content = StringField()
    13 
    14 TestData.objects.get_or_create(name='天地玄黄',defaults={'content':'abc123'})
    15 TestData.objects.get_or_create(name='宇宙洪荒',defaults={'content':'ABC123'})
    16 TestData.objects.get_or_create(name='天天向上',defaults={'content':'Abc123'})
    17 
    18 def print_arr(obj):
    19     print obj.name,obj.content
    20 
    21 def fuzzy_query_by_contains():
    22     print "
    ###使用mongoengine的contains进行查询"
    23     print "#contains区分大小写:"
    24     test_data_list = TestData.objects(content__contains='abc123')
    25     map(print_arr,test_data_list)
    26 
    27     print "#icontains不区分大小写:"
    28     test_data_list = TestData.objects(content__icontains='abc123')
    29     map(print_arr,test_data_list)
    30 
    31 def fuzzy_query_by_Q():
    32     print "
    ###使用Q来进行查询"
    33     test_data_list = TestData.objects(
    34         Q(name__icontains=u'天地') | Q(name__icontains=u'宇宙'))
    35     map(print_arr,test_data_list)
    36 
    37 def fuzzy_query_by_pymongo():
    38     print "
    ###使用raw queries,New in version 0.4"
    39     print "#单个查询条件"
    40     search = {
    41         '__raw__':{
    42             'content':{'$regex':'AS+d+'},
    43         },
    44     }
    45     test_data_list = TestData.objects(**search)
    46     map(print_arr,test_data_list)
    47 
    48     print "#多个查询条件"
    49     search = {
    50         '__raw__':{
    51             'name':{'$in':[re.compile(u'天天'),re.compile(u'宇宙')]},
    52         },
    53     }
    54     test_data_list = TestData.objects(**search)
    55     map(print_arr,test_data_list)
    56 
    57 if __name__ == '__main__':
    58     fuzzy_query_by_contains()
    59     fuzzy_query_by_Q()
    60     fuzzy_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':'AS+d+'}
        接着就是对多个关键词进行查询,对应的代码为:{'$in':[re.compile(u'天天'),re.compile(u'宇宙')]}

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

    1 def fuzzy_query_by_pymongo():
    2     print "#多个查询条件"
    3     keyword = u'天天 宇宙'
    4     search = {'__raw__' : {'name':{'$in':map(re.compile,keyword.split())}}}
    5     test_data_list = TestData.objects(**search)
    6     map(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.age
    4 True

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

     1 $ python mongodb_test.py
     2 
     3 ###使用mongoengine的contains进行查询
     4 #contains区分大小写:
     5 天地玄黄 abc123
     6 #icontains不区分大小写:
     7 天地玄黄 abc123
     8 宇宙洪荒 ABC123
     9 天天向上 Abc123
    10 
    11 ###使用Q来进行查询
    12 天地玄黄 abc123
    13 宇宙洪荒 ABC123
    14 
    15 ###使用raw queries,New in version 0.4
    16 #单个查询条件
    17 宇宙洪荒 ABC123
    18 天天向上 Abc123
    19 #多个查询条件
    20 宇宙洪荒 ABC123
    21 天天向上 Abc123
  • 相关阅读:
    SpringTask中cron表达式整理记录
    解决idea启动弹窗
    windows上安装kafka
    两种方式实现横向滚动条
    浅谈新的布局方式-flex
    不忘初衷,方得始终 ---总结一年的前端生涯
    javascript深入理解js闭包(转载)
    es6学习笔记--Interator和Generator(以及for-of的用法)
    根据HTML5的新方法 drag & drop 方法实现表格拖拽实例
    HTML5 拖放(Drag 和 Drop)详解与实例(转)
  • 原文地址:https://www.cnblogs.com/PandaBamboo/p/3878237.html
Copyright © 2020-2023  润新知