2015-03-17 3 views
2

У меня такая ситуация.Получает вспомогательные документы по geoNear - MongoDB

В нашей базе данных есть «хранимые» документы и «филиалы» в качестве поддокументов (от одного до многих).

В каждом филиале есть атрибут местоположения, который индексируется для поиска геолокации.

Итак, проблема:

{store:{"name":"store1", branchoffices:[{"name":"bo1","location":[ -70.64341379999999, -33.4268697 ]}, {"name":"bo2","location":[80.4,43.3]}]}} 

Если я это сделать агрегацию:

Store.collection.aggregate(
     [{ 
      "$geoNear"=>{"near"=>[ -70.64341379999999, -33.4268697 ], 
      "distanceField"=>"distance", 
      "maxDistance"=>0.0900899926955034} 
     }, 
     { "$unwind" => "$branchoffices"} 
    ] 

В результате это каждое отделение с полем расстояния повторяется в обеих строках или возвращаемых записей. Когда только что нашел один филиал в geoNear.

Существует какой-то способ просто вернуть поддокумент или поддокументы, которые являются результатом поиска геолокации?

Спасибо.

ответ

2

Опция под $geoNear является includeLocs следующим образом:

Store.aggregate([ 
    { "$geoNear": { 
     "near": [ -70.64341379999999, -33.4268697 ], 
     "distanceField": "distance", 
     "maxDistance": 0.0900899926955034, 
     "includeLocs": "location" 
    }} 
]) 

Выход имеет совпадающий "расположение" на "расстояние" в поле вывода:

{ 
    "_id" : ObjectId("5507b18d1c3bdce0535aecd0"), 
    "name" : "store1", 
    "branchoffices" : [ 
      { 
        "name" : "bo1", 
        "location" : [ 
          -70.64341379999999, 
          -33.4268697 
        ] 
      }, 
      { 
        "name" : "bo2", 
        "location" : [ 
          80.4, 
          43.3 
        ] 
      } 
    ], 
    "distance" : 0, 
    "location" : [ 
      -70.64341379999999, 
      -33.4268697 
    ] 
} 

Если вы хотите конкретный суб-документ в массиве, который был использован в матче в полной детализации, тогда вы можете продолжить использование фильтра с использованием $redact:

Store.aggregate([ 
    { "$geoNear": { 
     "near": [ -70.64341379999999, -33.4268697 ], 
     "distanceField": "distance", 
     "maxDistance": 0.0900899926955034, 
     "includeLocs": "location" 
    }}, 
    { "$redact": { 
     "$cond": [ 
      { "$eq": [ "$location", "$$ROOT.location" ] }, 
      "$$DESCEND", 
      "$$PRUNE" 
     ] 
    }} 
]) 

Или в версиях до MongoDB 2.6, как это:

Store.aggregate([ 
    { "$geoNear": { 
     "near": [ -70.64341379999999, -33.4268697 ], 
     "distanceField": "distance", 
     "maxDistance": 0.0900899926955034, 
     "includeLocs": "location" 
    }}, 
    { "$unwind": "$branchoffices" }, 
    { "$project": { 
     "name": 1, 
     "branchoffices": 1, 
     "matched": { 
      "$eq": [ "$location", "$branchoffices.location" ] 
     } 
    }}, 
    { "$match": { "matched": 1 } }, 
    { "$group": { 
     "_id": "$_id", 
     "name": { "$first": "$name" }, 
     "branchoffices": { "$push": "$branchoffices" }, 
     "distance": { "$first" "$distance" } 
    }} 
]) 

Вы должны, вероятно, отметить, что использование объектов в поддокументе не всегда является оптимальным решением и, как правило, не подходят для различных задания. Например, если ваши данные в массиве могут содержать «несколько» местоположений, которые были бы «близки» к запрашиваемой точке, тогда только единственная «ближайшая» точка могла бы быть подобранной.

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

+0

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

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