2014-11-12 3 views
3

У меня есть коллекция с субдокументом, состоящим из записей более 40K. Мой общий запрос занимает около 300 секунд. Я пробовал оптимизировать то же самое с использованием соединения, а также с помощью многозначного индексирования, которое завершается через 180 секунд.MongoDB-Query Optimization

Мне по-прежнему требуется сокращение времени выполнения запроса.

вот моя коллекция:

{ 
    "_id" : ObjectId("545b32cc7e9b99112e7ddd97"), 
    "grp_id" : 654, 
    "user_id" : 2, 
    "mod_on" : ISODate("2014-11-06T08:35:40.857Z"), 
    "crtd_on" : ISODate("2014-11-06T08:35:24.791Z"), 
    "uploadTp" : 0, 
    "tp" : 1, 
    "status" : 3, 
    "id_url" : [ 
    {"mid":"xyz12793"}, 
    {"mid":"xyz12794"}, 
    {"mid":"xyz12795"}, 
    {"mid":"xyz12796"} 
    ], 
    "incl" : 1, 
    "total_cnt" : 25, 
    "succ_cnt" : 25, 
    "fail_cnt" : 0 
} 

и после моего запрос

db.member_id_transactions.aggregate([ { '$match': 
          { id_url: { '$elemMatch': { mid: 'xyz12794' } } } }, 
          { '$unwind': '$id_url' }, 
          { '$match': { grp_id: 654, 'id_url.mid': 'xyz12794' } } ]) 

кто-нибудь сталкивались с таким же вопросом?

вот о/р для совокупного запроса с объяснить опцию

{ 
    "result" : [ 
     { 
      "_id" : ObjectId("546342467e6d1f4951b56285"), 
      "grp_id" : 685, 
      "user_id" : 2, 
      "mod_on" : ISODate("2014-11-12T11:24:01.336Z"), 
      "crtd_on" : ISODate("2014-11-12T11:19:34.682Z"), 
      "uploadTp" : 1, 
      "tp" : 1, 
      "status" : 3, 
      "id_url" : [ 
      {"mid":"xyz12793"}, 
      {"mid":"xyz12794"}, 
      {"mid":"xyz12795"}, 
      {"mid":"xyz12796"} 
      ], 
      "incl" : 1, 
      "__v" : 0, 
      "total_cnt" : 21406, 
      "succ_cnt" : 21402, 
      "fail_cnt" : 4 
     } 
    ], 
    "ok" : 1, 
    "$gleStats" : { 
     "lastOpTime" : Timestamp(0, 0), 
     "electionId" : ObjectId("545c8d37ab9cc679383a1b1b") 
    } 
} 

ответ

3

Один из способов уменьшить количество записей, которые фильтруются дополнительно должен включать поле grp_id, в первом $match оператора.

db.member_id_transactions.aggregate([ 
{$match:{ "id_url.mid": 'xyz12794',"grp_id": 654 } }, 
{$unwind: "$id_url" }, 
{$match: { "id_url.mid": "xyz12794" } } 
]) 

Посмотрите, как работает сейчас. Добавьте grp_id в индекс, чтобы получить лучшее время отклика.

Вышеуказанный запрос агрегации, хотя он работает, не нужен. так как вы не изменяете структуру документа, и вы ожидаете, что только один элемент в массиве будет соответствовать условию фильтра, вы можете просто использовать простые find и project.

db.member_id_transactions.find(
{ "id_url.mid": "xyz12794","grp_id": 654 }, 
{"_id":0,"grp_id":1,"id_url":{$elemMatch:{"mid":"xyz12794"}}, 
"user_id":1,"mod_on":1,"crtd_on":1,"uploadTp":1, 
"tp":1,"status":1,"incl":1,"total_cnt":1, 
"succ_cnt":1,"fail_cnt":1 
} 
) 
+1

Согласен. Просто чтобы добавить. В частности, когда вы даже «думаете» вам нужно использовать '$ unwind', вы должны« сначала попытаться отфильтровать документы до вашего минимального набора соответствия, но это должно быть общее правило запроса. Разъясняя второй оператор, вам не нужен агрегат и, следовательно, '$ unwind', когда вы ожидаете, что только один элемент в массиве будет соответствовать условию фильтра. '$ elemMatch' тоже здесь не нужен, поскольку' 'id_url.mid": "xyz12794" 'будет делать. Тот же принцип, только в одном «поле». –

+0

Nice Explanation. Обновите мой ответ на основе ваших комментариев. (Удален ненужный оператор '$ elemMatch'.) – BatScream

+0

Спасибо BatScream за решение ... попробовал поиск, и он работает как шарм ... спасибо тонну за сохранение моего дня .... – Charles