2013-05-25 4 views
1

Предположим, у меня есть список запросов pymongo и документа. документ может быть (или нет) согласован одним или несколькими запросами pymongo.Определите, соответствует ли документ mongoengine необработанному запросу pymongo в коде

например.

Вот мой документ:

> db.my_collection.findOne() 
{ 
    "EmbeddedDoc" : { 
     "values" : [ 
      NumberLong(1), 
      NumberLong(2) 
     ] 
    }, 
    "_id" : ObjectId("515407bbc118555eea07fea5"), 
    "some_other_value" : "Val", 
    "my_id" : NumberLong(42), 
} 

Вот список необработанных запросов PyMongo (связанный с каким-то списком целых чисел):

list_of_queries = [ 
    ({'EmbeddedDoc.values': 2}, [1, 3, 5]) 
    ({'some_other_value': 'H2G2'}, [6, 5]) 
    ({'some_other_value': 'Val'}, [10, 4]) 
    ({'my_id': {'$gte': 256}}, [3, 13, 2]) 
] 

Я хочу знать конкатенации списков ints, для запросов, соответствующих конкретному документу. В случае выше, что было бы [1, 3, 5, 10, 4]

Что я сделал, до сих пор, было запрашивая дБ каждый раз (здесь метод на MyCollection Наследование mongoengine Document):

def get_list_of_int(self): 
    ints = [] 
    for query, list_of_ints in list_of_queries: 
     if bool(MyCollection.objects(my_id=self.my_id, __raw__=query)): 
      ints.extend(list_of_ints) 
    return ints 

Однако это опрашивает db каждый раз. Несмотря на то, что это быстро (есть индекс на my_id), мне было интересно, есть ли способ определить, соответствует ли экземпляр Document конкретному запросу внутри кода вместо запроса на db (список запросов может быть сколь угодно длинным).

ответ

0

Я думаю, что это может (или не быть) невозможно.

Я подозреваю, что поиск mongodb выполняется на сервере, в то время как вы хотите проверить результат на клиенте. Я сомневаюсь, что привязки pymongo могут выполнять такую ​​же операцию на стороне клиента.

Рассмотрите следующие проблемы, связанные с разложением: map - выберите подходящие документы и reduce - объединить целые числа. Принципиально ваши варианты для достижения хорошей производительности являются:

  1. реализовать этап карты в Python (новый) и уменьшить в Python (уже)
  2. сохранить мап этапа в JS и реализации сократить этап в JS (новом)

Этап отображения для произвольных JS-запросов в Python кажется очень большой работой.

Уменьшить этап в JS требует, чтобы вы создавали функцию сокращения во время выполнения, я думаю, но это не должно быть слишком сложно.

http://docs.mongodb.org/manual/core/map-reduce/

+0

Привет, во-первых спасибо за вашу anwser. Я знаю, что поиск выполняется на стороне db-сервера, но я надеялся, что метод на стороне клиента, который дал конкретный документ, знает, совпадает ли запрос или нет (в pymongo, mongoengine или другой lib).Я прыгал, был какой-то код, сделанный для таких случаев (пока не нашел ничего подобного). более того, я не совсем понял вторую часть вашего ответа, можно ли быть более явным? – astreal

+0

Я неправильно понял вашу проблему, удалил оригинальную вторую часть ответа и написал новую опцию - уменьшить карту на стороне сервера. –

+0

Все на стороне JS на самом деле не вариант в моей архитектуре. Таким образом, он остается отображением в Python. Действительно, это большая работа, но в проекте мы решили пойти на этот вариант для «простого» подмножества запросов («просто» в том смысле, что мы не рассматриваем запросы с помощью $ или (могут быть два отдельных запроса) , с $ regex, Geospatial selector и т. д.). Однако мне все еще интересно, существует ли библиотека, которая делает такое сопоставление? – astreal

0

Рискну сказать, что вы не можете уйти с запросом к базе данных каждый раз. Однако добавление слоя кеширования, вероятно, значительно ускорит процесс. Я предполагаю, что одни и те же запросы могут запускаться более одного раза. Если нет, кэширование не будет работать для вас вообще.

Вот некоторые примеры кода (я предлагаю вам использовать надлежащий механизм кэширования. Код только для иллюстрации)

cache = {} 
def get_list_of_int(self): 
ints = [] 
for query, list_of_ints in list_of_queries: 
    if query in cache: 
     ints.extend(list_of_ints if cache[query] else []) 
    if bool(MyCollection.objects(my_id=self.my_id, __raw__=query)): 
     cache[query] = True 
     ints.extend(list_of_ints) 
    cache[query] = False 
return ints 
+0

Кэширование мне не поможет, список запросов не повторяется вообще. они могут перекрываться (несколько запросов соответствуют экземпляру коллекции), но определенно не совпадают. Спасибо за твое мнение. – astreal

Смежные вопросы