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

Consulta MongoDb próxima/geonear com distância variável


Você não poderá fazer isso com uma consulta normal, pois não pode definir dinamicamente a distância por documento. A partir do MongoDB 2.4, você pode fazer isso com a estrutura de agregação, pois eles adicionaram o operador geoNear aos inícios dos pipelines.

A primeira etapa será o geoNear que é muito semelhante ao comando geonear. Como resultado, também obteremos a distância do ponto especificado (10,10) ao documento.

Na segunda etapa, precisaremos usar o operador de projeto para adicionar a diferença entre o campo maximumDistance e a distância geoNear calculada.

Por fim, combinamos os documentos que possuem delta positivo ((max - distance)> 0).

Aqui está o pipeline usando o Driver Java assíncrono classes auxiliares de.
package example;

import static com.allanbank.mongodb.builder.AggregationProjectFields.include;
import static com.allanbank.mongodb.builder.QueryBuilder.where;
import static com.allanbank.mongodb.builder.expression.Expressions.field;
import static com.allanbank.mongodb.builder.expression.Expressions.set;
import static com.allanbank.mongodb.builder.expression.Expressions.subtract;

import com.allanbank.mongodb.bson.element.ArrayElement;
import com.allanbank.mongodb.builder.Aggregate;
import com.allanbank.mongodb.builder.AggregationGeoNear;
import com.allanbank.mongodb.builder.GeoJson;

public class AggregateGeoNear {
    public static void main(String[] args) {
        Aggregate aggregate = Aggregate
                .builder()
                .geoNear(
                        AggregationGeoNear.builder()
                                .location(GeoJson.p(10, 10))
                                .distanceField("distance"))
                .project(
                        include("name", "location", "maximumDistance"),
                        set("delta",
                                subtract(field("maximumDistance"),
                                        field("distance"))))
                .match(where("delta").greaterThanOrEqualTo(0)).build();

        System.out
                .println(new ArrayElement("pipeline", aggregate.getPipeline()));
    }
}

E aqui está o pipeline criado:
pipeline : [
  {
    '$geoNear' : {
      near : [
        10, 
        10
      ],
      distanceField : 'distance',
      spherical : false,
      uniqueDocs : true
    }
  }, 
  {
    '$project' : {
      name : 1,
      location : 1,
      maximumDistance : 1,
      delta : {
        '$subtract' : [
          '$maximumDistance', 
          '$distance'
        ]
      }
    }
  }, 
  {
    '$match' : {
      delta : { '$gte' : 0 }
    }
  }
]

HTH - Rob.

P.S. Os construtores acima estão usando um pré-lançamento da versão 1.2.0 do driver. O código está passando pela matriz de compilação enquanto digito e deve ser lançado até sexta-feira, 22 de março de 2013.