Возьмите этот запрос:
{ 'location' : { '$near' : [x,y], '$maxDistance' : this.field } }
Я хочу присвоить $maxDistance значение указанного поля из текущего оцениваемого документа. Это возможно?
Возьмите этот запрос:
{ 'location' : { '$near' : [x,y], '$maxDistance' : this.field } }
Я хочу присвоить $maxDistance значение указанного поля из текущего оцениваемого документа. Это возможно?
Да, это возможно. Вместо этого вы просто используете $geoNear
. Остерегайтесь уловов и внимательно читайте.
Предполагая, что вы намерены сохранить поле, такое как "travelDistance"
, чтобы указать в документе, что любые такие поиски должны быть «внутри» указанного расстояния от запрашиваемой точки, чтобы быть действительными. Затем мы просто запрашиваем и оцениваем условие с помощью $redact
:
db.collection.aggregate([
{ "$geoNear": {
"near": {
"type": "Point",
"coordinates": [x,y]
},
"spherical": true,
"distanceField": "distance"
}},
{ "$redact": {
"$cond": {
"if": { "$lte": [ "$distance", "$travelDistance" ] },
"then": "$$KEEP",
"else": "$$PRUNE"
}
}}
])
Единственная загвоздка в том, что $geoNear
так же, как и $near
в первую очередь вернет только определенное количество документов "near". Вы можете настроить это с помощью параметров, но в отличие от общей формы запроса, это в основном гарантирует, что возможные возвращаемые результаты будут меньше, чем указанные «ближайшие» числа.
Пока вы осознаете это, это совершенно справедливо.
На самом деле это общий способ определения того, что находится «близко» в радиусе.
Также помните о «расстоянии» в зависимости от того, как вы сохранили координаты. В качестве устаревших пар координат расстояния будут указаны в радианах, которые вам, вероятно, потребуются математические расчеты для преобразования в километры или мили.
При использовании GeoJSON расстояния всегда считаются в метрах, как стандартный формат.
Все математические заметки есть в документации.
Примечание Внимательно прочитайте документацию
$geoNear
. . Такие параметры, как"spherical"
, необходимы для индексов"2dsphere"
, таких как вы должны иметь для координат реального мира. Также может потребоваться применить"limit"
, чтобы увеличить результат документа по умолчанию, равный 100, для дальнейшей обрезки.
Поскольку в комментариях упоминается весенний монго, то для этого делается то же самое:
Aggregation aggregation = newAggregation(
new AggregationOperation() {
@Override
public DBObject toDBObject(AggregationOperationContext context) {
return new BasicDBObject("$geoNear",
new BasicDBObject(
"near", new BasicDBObject(
"type","Point")
.append("coordinates", Arrays.asList(20,30))
)
.append("spherical",true)
.append("distanceField","distance")
);
}
},
new AggregationOperation() {
@Override
public DBObject toDBObject(AggregationOperationContext context) {
return new BasicDBObject("$redact",
new BasicDBObject(
"$cond", Arrays.asList(
new BasicDBObject("$lte", Arrays.asList("$distance", "$travelDistance")),
"$$KEEP",
"$$PRUNE"
)
)
);
}
}
);
$near
? $geoNear
нужно?
- person anat0lius; 23.06.2017
$geoNear
— это агрегированная версия $near
. Вам нужна агрегация и $geoNear
, чтобы вернуть расстояние для сравнения. Вы ничего не теряете. Если вы все еще не понимаете, задайте новый вопрос.
- person Neil Lunn; 23.06.2017
$geoNear
требует индекса 2dsphere
, хотя мне он не нужен, мне было бы достаточно 2d
индекса ($near
). Спасибо еще раз
- person anat0lius; 23.06.2017
2d
, вам не нужно включать spherical
, просто оставьте его вне параметров конвейера.
- person Neil Lunn; 23.06.2017
$redact
или, что еще хуже,$where
. Всегда был. - person Neil Lunn   schedule 22.06.2017