mongoDB:忽略空字段的多值字段搜索

时间:2014-04-04 08:29:41

标签: mongodb mongodb-query nosql

我正在尝试在几个字段上进行搜索,其中一些字段可以留空。 给出MongoDB中的以下Json文档(这里只有三个字段,但实际上是N个字段,N> 10):

{
    'first_name' : 'value_X',
    'last_name' : 'value_Y',
    'mail_adress' : 'value_Z'

}

然后让我们假设一个表单,用户可以在其中输入名字,姓氏,邮件地址和电话号码的值。 如果填充了所有字段,则MongoDB中的查询如下所示:

db.collection.find( {
                        'first_name' : 'value_A',
                        'last_name' : 'value_B',
                        'mail_adress' : 'value_C'

                    }
                )

我遇到的问题是用户可能会将某些字段留空: 这意味着我的查询也可以变为:

db.collection.find({ 'first_name' : 'value_A' })

db.collection.find( {'last_name' : 'value_B'})  

db.collection.find( {'mail_adress' : 'value_C'})

db.collection.find( {'first_name' : 'value_A','last_name' : 'value_B'})

db.collection.find( {'first_name' : 'value_A','last_name' : 'value_C'})

db.collection.find( {'last_name' : 'value_B','mail_adress' : 'value_C'})

我想知道是否需要为每个特定实例编写查询? 我还想过根据用户输入的字段动态生成查询,因为查询是Json doucment会很容易。

我也想知道MongoDB是否可以忽略字段,如果它们为空(但我不想在我的查询中失去性能)

任何人都可以帮助我吗?感谢

编辑于20140404下午6点:部分答案

这是带有Aditya建议的Python代码。 我还添加了关于在前端生成查询的python代码,如svjn建议:

'''
Created on 4 Apr 2014

@author: scoulombel
'''

import pymongo
from pymongo import MongoClient
import random
import string



# fill the database
def fillCollection(collection):
    doc =   {
      'first_name' : 'value_X',
      'last_name' : 'value_Y',
      'mail_adress' : 'value_Z'

    }

    docID = collection.insert(doc)

    for _ in range(0,10):
        doc = {
           'first_name' : ''.join(random.choice(string.ascii_uppercase) for _ in range(4)) + ''.join(random.choice(string.digits) for _ in range(4)),
           'last_name' : ''.join(random.choice(string.ascii_uppercase) for _ in range(4)) + ''.join(random.choice(string.digits) for _ in range(4)),
           'mail_adress' : ''.join(random.choice(string.ascii_uppercase) for _ in range(4)) + ''.join(random.choice(string.digits) for _ in range(4))

        }
        docID = collection.insert(doc)

# read data in a cursor
def readCursor(cursor):
    object_list = []
    count = 0   
    for doc in cursor :
        del doc["_id"]
        count += 1
        doc['resOrder'] =  count
        object_list.append(doc)

    print object_list

if __name__ == '__main__':  
    #client = MongoClient()
    client = MongoClient('ip', 'port')
    db = client.test_OR_AND_DB      
    collection = db.collection

    fillCollection(collection)

    # SEARCH VALUE which can be null or not    
    value_A = 'value_X'
    value_B = 'null' #'value_Y'
    value_C = 'null' #'value_Z'

    # APPROACH 1 : ADITYA answer for search
    cursor1 = db.collection.find(
                                {
                         '$or' : [
                                    { '$and' : [ {'first_name' : { '$ne': 'null' }}, {'first_name' : value_A } ]},
                                    { '$and' : [ {'last_name' :  { '$ne': 'null' }}, {'last_name'  : value_B  } ]}, 
                                    { '$and' : [ {'mail_adress' :{ '$ne' :'null' }}, {'mail_adress':value_C } ]}
                               ]
                        }
                        )

    readCursor(cursor1)

    # APPROACH 2 ; create a JSON representing the query dynamically
    path_value_dict = {'first_name':value_A, 'last_name':value_B, 'mail_address':value_C} # if embedded it would be for instance name.first_name 
    query= {}
    for key in path_value_dict.keys():
        if path_value_dict[key] != 'null':
            query[key] = path_value_dict[key]


    print query
    cursor2 = db.collection.find({'first_name': 'value_X', 'mail_adress': 'value_Z'})
    readCursor(cursor2) 

1 个答案:

答案 0 :(得分:0)

使用Mongodb $or运算符进行查询。

$或运算符对两个或更多<expressions>的数组执行逻辑OR运算,并选择满足至少一个<expressions> 的文档。

使用:

db.collection.find({
     $or : [{ $and : [ {'first_name' : { $ne:null }, {'first_name' :'value_A' }]},
            { $and : [ {'last_name' :  { $ne:null }, {'last_name'  :'value_B' }]}, 
            { $and : [ {'mail_addres' :{ $ne:null }, {'mail_addres':'value_C'}]}
           ]}
    );