Извлечение ссылок mongoDB требует времени

Я использую mongoengine в качестве картографа Object-Document. Вот краткое описание коллекций, вызывающих проблему. Каждый документ в коллекции A может иметь список ссылок на документы в коллекции B.

class A(Document): 
    list_b = ListField(EmbeddedDocumentField(EB))
    #other fields are not mentioned.

class EB(EmbeddedDocument):
    b_reference = ReferenceField('B')
    loc = GeoPointField()

class B(Document):
    name = StringField()
    #other fields are not mentioned.

Когда я пытаюсь получить доступ к объектам списка определенного документа с помощью

document_of_A.list_b

время выполнения вышеуказанной строки зависит от количества ссылок, присутствующих в списке. Например. для 100 ссылок в списке требуется 100 мс.

Есть ли лучший способ получить ссылки?, чтобы сократить время выполнения вышеупомянутой строки.


person Yashwanth Kumar    schedule 20.04.2013    source источник
comment
Добро пожаловать в проблемы организации документов MongoDb. :) docs.mongodb.org/manual/core/data-modeling Вам нужны все указанные документы?   -  person WiredPrairie    schedule 20.04.2013
comment
Индексируются ли ссылки на документ B таким образом, чтобы запрос на документы, относящиеся к A, мог быть возвращен сразу?   -  person WiredPrairie    schedule 20.04.2013
comment
нет, в поле list_b нет индекса.   -  person Yashwanth Kumar    schedule 21.04.2013
comment
Если они не проиндексированы, MongoDB потребуется искать потенциально совпадения в каждом документе.   -  person WiredPrairie    schedule 21.04.2013
comment
никаких изменений даже после того, как я создал индекс.   -  person Yashwanth Kumar    schedule 22.04.2013
comment
Вам нужно увидеть, какой запрос отправляется. И/или какие индексы используются через explain: api.mongodb.org/python/1.11 /tutorial.html   -  person WiredPrairie    schedule 22.04.2013
comment
Запрос возвращает документы коллекции A. Время запроса не является проблемой, но когда я перебираю каждый документ и пытаюсь получить список ссылок, это занимает значительное время. Я не понимаю эту часть, где время тратится только на доступ к list_b.   -  person Yashwanth Kumar    schedule 22.04.2013
comment
Если вам нужно делать отдельные запросы для каждого вторичного документа, это, вероятно, будет медленным, если вы не сможете получить их все сразу (найти все, где B принадлежит A).   -  person WiredPrairie    schedule 22.04.2013


Ответы (1)


Вы должны использовать флаг select_related при запросе, если хотите быстро получить все ссылки. Обратите внимание, что поиск ссылок будет стоить дополнительных запросов, а select_related() предназначен для уменьшения количества обращений к mongodb.

# Single document lookup
document_of_A.select_related(2)

# Queryset
A.objects.select_related(2)

Почему 2 для поиска select_related? Ну, рекурсивная глубина:

  1. искать любые ссылки в самом списке
  2. поиск ссылок в отдельных встроенных документах
person Ross    schedule 23.04.2013
comment
когда я использую select_related(2) как часть запроса, время запроса такое же, но оптимизация не достигается, когда я пытаюсь получить ссылки. Где, когда я использую select_related(2) как часть одного документа, время ссылок сохраняется, но теперь часть select_related(2) требует времени. - person Yashwanth Kumar; 24.04.2013
comment
Ах, может быть, для запроса это должно быть select_related(3), извините. Число — это глубина, на которую он должен опускаться. - person Ross; 26.04.2013
comment
мой плохой, тест, который я сделал ранее, был неправильным. select_related(2) теперь работает. - person Yashwanth Kumar; 26.04.2013
comment
@Ross, как преобразовать результат select_related() в_json()? - person holms; 02.06.2014