MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

Geoespacial $ próximo ao valor do campo do documento atual


Sim é possivel. Você acabou de usar $geoNear em vez de. Cuidado com as capturas e leia com atenção.

Presumindo que sua intenção é armazenar um campo como "travelDistance" para indicar no documento que tais buscas devem estar "dentro" daquela distância fornecida do ponto consultado para serem válidas. Então, simplesmente consultamos e avaliamos a condição com $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"
    }
  }}
])

O único problema é que $geoNear assim como $near retornará apenas um certo número de documentos "perto" em primeiro lugar. Você pode ajustar isso com as opções, mas ao contrário do formulário de consulta geral, isso basicamente garante que os eventuais resultados retornados serão menores do que os números "mais próximos" especificados.

Contanto que você esteja ciente disso, então isso é perfeitamente válido.

Na verdade, é a maneira geral de lidar com a qualificação do que está "próximo" dentro de um raio.

Fique atento também à "distância" de acordo com a forma como você tem as coordenadas armazenadas. Como pares de coordenadas herdadas, as distâncias estarão em radianos que você provavelmente precisará fazer as contas para converter em quilômetros ou milhas.

Se estiver usando GeoJSON, as distâncias são sempre consideradas em metros, como o formato padrão.

Todas as notas matemáticas estão na documentação.

N.B Leia o $geoNear documentação com cuidado. Opções como "spherical" são necessários para "2dsphere" índices, como você deve ter para coordenadas do mundo real. Também "limit" pode precisar ser aplicado para aumentar além do resultado padrão de 100 documentos, para corte adicional.

Como os comentários mencionam o spring mongo, aqui está basicamente a mesma coisa feita para isso:
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"
             )
          )
       );
     }
    }
);