sql >> Base de Datos >  >> NoSQL >> MongoDB

Spring Boot Data y MongoDB - Consulta de matriz de subdocumento de filtro

Bueno, en Spring Data este tipo de consultas no es trivial .

Malas noticias:
Spring Data Repository no tiene una solución para MongoDB Aggregation . Por lo tanto, no puede implementar en MongoRepository ningún método para hacerlo, como aggregateBy...

Buenas noticias:
Spring Data proporciona MongoTemplate class que le permite ejecutar consultas complejas, como lo haría en el shell estándar de MongoDB.

Entonces, como solo desea exclude subdocumento que no coincide con alguna condición, necesitamos definir los pipelines agregados .

Supongo:

zip codes are Numeric (In your example is string)
And, to exclude subdocument, we filter by `zip`
There is no any other filter

La agregación de MongoDB sería:

db.person.aggregate([
    {$unwind: "$address"},
    {$match: {"address.zip": 12345}},
    {$group: { _id: { "firstName":"$firstName", "lastName":"$lastName", _id:"$_id" }, address: { $push: "$address" } } },
    {$project: {_id:0, "firstName":"$_id.firstName", "lastName":"$_id.lastName", "address": "$address"}}
])

Si todos los filtros tienen éxito, obtendremos:

[ 
    {
        "address" : [ 
            {
                "zip" : 12345
            }, 
            {
                "zip" : 12345
            }
        ],
        "firstName" : "George",
        "lastName" : "Washington"
    }
]

Ahora, en Spring Data, necesita agregar algunos cambios en su proyecto:

Primero, encuentra tu mongo-config.xml donde necesitas agregar:

<!-- Define the mongoDbFactory with your database Name  -->
<mongo:db-factory uri="mongodb://user:[email protected]:27017/db"/>

<!-- Define the MongoTemplate  -->
<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
    <constructor-arg name="mongoDbFactory" ref="mongoDbFactory" />
</bean>

MongoTemplate es la clase central de la compatibilidad con MongoDB de Spring que proporciona conjuntos de características para interactuar con la base de datos. La plantilla ... proporciona una asignación entre sus objetos de dominio y documentos MongoDB . Más información

Segundo, en su @Service clase, agregue el siguiente código para que se cargue en @PostConstruct

@Autowired
private MongoOperations mongoOperations;

...

public List<Person> findByAddressZipCode(int zip) {

    List<AggregationOperation> list = new ArrayList<AggregationOperation>();
    list.add(Aggregation.unwind("address"));
    list.add(Aggregation.match(Criteria.where("address.zip").is(zip)));
    list.add(Aggregation.group("firstName", "lastName").push("address").as("address"));
    list.add(Aggregation.project("firstName", "lastName", "address"));
    TypedAggregation<Person> agg = Aggregation.newAggregation(Person.class, list);
    return mongoOperations.aggregate(agg, Person.class, Person.class).getMappedResults();
}

Nota: Ambos, Person y Address debería tener un constructor vacío por defecto!