zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    Leetcode 15 3Sum
    Leetcode 383 Ransom Note
    用i个点组成高度为不超过j的二叉树的数量。
    配对问题 小于10 1.3.5
    字符矩阵的旋转 镜面对称 1.2.2
    字符串统计 连续的某个字符的数量 1.1.4
    USACO twofive 没理解
    1002 All Roads Lead to Rome
    USACO 5.5.1 求矩形并的周长
    USACO 5.5.2 字符串的最小表示法
  • 原文地址:https://www.cnblogs.com/PandaBamboo/p/3878237.html
Copyright © 2011-2022 走看看