MongoDB: как я могу заказать по расстоянию, учитывая несколько полей?
У меня есть коллекция, в которой хранится информация о врачах. Каждый врач может работать в частной практике и / или в больницах. Коллекция имеет следующие соответствующие поля (имеются геопространственные индексы на обеих частных практиках.адрес.Лок и больницы.адрес.loc):
{
"name" : "myName",
"privatePractices" : [{
"_id": 1,
"address" : {
"loc" : {
"lng" : 2.1608502864837646,
"lat" : 41.3943977355957
}
}
},
...
],
"hospitals" : [{
"_id": 5,
"address" : {
"loc" : {
"lng" : 2.8192520141601562,
"lat" : 41.97784423828125
}
}
},
...
]
}
Я пытаюсь запросить эту коллекцию, чтобы получить список врачей, упорядоченных по расстоянию от заданной точки. Вот где я застрял:
Следующие запросы возвращают список врачей, упорядоченных по расстоянию к точке, определенной в $nearSphere, рассматривая только один из двух типов местоположения:
{ "hospitals.address.loc" : { "$nearSphere" : [2.1933, 41.4008] } }
{ "privatePractices.address.loc" : { "$nearSphere" : [2.1933, 41.4008] } }
Все, чего я хочу, - это чтобы врачи были выписаны ближайшей больницей или частной практикой, какой бы она ни была. Возможно ли это сделать на одном запросе Mongo?
План B состоит в том, чтобы использовать запросы выше, а затем вручную упорядочить результаты вне Mongo (например. использование Linq). Для этого два моих запроса должны возвращать расстояние от каждой больницы или частной практики до точки $ nearSphere. Является это возможно сделать в монго?
EDIT-прикладное решение (MongoDB 2.6): Я использовал свой собственный подход, вдохновленный тем, что предлагает Нил Ланн в своем ответе: я добавил поле в документе доктора для сортировки, содержащее массив со всеми местоположениями доктора.
Я попробовал этот подход в MongoDB 2.4 и MongoDB 2.6, и результаты разные. Запросы на 2.4 возвращали дубликаты докторов, у которых было больше, чем местоположение, даже если _id был включен в запрос фильтр. Запросы на 2.6 возвращали корректные результаты.
1 ответ:
Я бы надеялся получить здесь немного больше информации, но основы все еще применимы. Таким образом, общая проблема, на которую вы наткнулись, заключается в попытке иметь "два" поля местоположения на том, что, по-видимому, является вашими документами врачей.
Есть еще одна проблема с этим подходом. У вас есть" местоположения " внутри массивов в вашем документе/ это не даст вам ошибку при создании индекса, но он также не будет работать, как вы ожидаете. Большая проблема здесь заключается в том, что находясь внутри массив, вы можете найти документ, который "содержит" ближайшее местоположение, но тогда вопрос в том, "какой", так как ничего не делается, чтобы повлиять на содержимое массива.
Основная проблема, однако, заключается в том, что вы не можете иметь более одного геопространственного индекса на запрос. Но чтобы действительно получить то, что вы хотите, переверните проблему с ног на голову и, по сути, прикрепите врачей к местам, которые находятся в другом месте.Например, здесь коллекция" практики " или такая:
{ "type": "Hospital", "address" : { "loc" : { "lng" : 2.8192520141601562, "lat" : 41.97784423828125 } }, "doctors": [ { "_id": 1, "name": "doc1", "specialty": "bones" }, { "_id": 2, "name": "doc2", "specialty": "heart" } ] } { "type": "Private", "address" : { "loc" : { "lng" : 2.1608502864837646, "lat" : 41.3943977355957 } }, "doctors": [ { "_id": 1, "name": "doc1", "specialty": "bones" }, { "_id": 3, "name": "doc3", "specialty": "brain" } ] }
Преимущество вот что у вас есть вот что как одна коллекция и все в одном индексе вы можете просто получить оба "типа" и правильно упорядочить по расстоянию или в пределах границ или независимо от того, что ваши гео-запросы должны быть. Это позволяет избежать проблем с другой формой моделирования.
Что касается информации о "врачах", то, конечно, вы на самом деле храните отдельную коллекцию для полной информации о врачах и, возможно, даже храните массив значений
_id
для документов о местоположении. Но главное здесь заключается в том, что вы обычно можете жить с "встраиванием" некоторой полезной поисковой информации в коллекцию, которая поможет вам.Это, кажется, лучший вариант здесь, и соответствие врача критериям изнутри местоположения-это то, что может быть сделано, где как поиск или сортировка ближайшей записи внутри массива-это то, что не будет поддерживаться самим MongoDB и приведет к тому, что вы примените математику самостоятельно при обработке результатов.