Comment pourrais-je convertir la requête MongoDB suivante en requête à utiliser par mon Java Spring? Je ne trouve pas un moyen d'utiliser pipeline
avec le recherche méthode.
Voici la requête que j'essaie de convertir. Je veux également noter que je n'ai pas utilisé $unwind
car je voulais que deliveryZipCodeTimings
reste en tant que collection groupée dans l'objet de retour.
db.getCollection('fulfillmentChannel').aggregate([
{
$match: {
"dayOfWeek": "SOME_VARIABLE_STRING_1"
}
},
{
$lookup: {
from: "deliveryZipCodeTiming",
let: { location_id: "$fulfillmentLocationId" },
pipeline: [{
$match: {
$expr: {
$and: [
{$eq: ["$fulfillmentLocationId", "$$location_id"]},
{$eq: ["$zipCode", "SOME_VARIABLE_STRING_2"]}
]
}
}
},
{
$project: { _id: 0, zipCode: 1, cutoffTime: 1 }
}],
as: "deliveryZipCodeTimings"
}
},
{
$match: {
"deliveryZipCodeTimings": {$ne: []}
}
}
])
Sur la base des informations fournies par @dnickless, j'ai pu résoudre ce problème. Je publierai la solution complète dans l'espoir qu'elle aide quelqu'un d'autre à l'avenir.
J'utilise mongodb-driver: 3.6.4
Tout d'abord, j'ai dû créer une classe d'opération d'agrégation personnalisée afin de pouvoir passer une requête mongodb JSON personnalisée à utiliser dans l'opération d'agrégation. Cela me permettra d'utiliser pipeline
dans un $lookup
qui n'est pas pris en charge avec la version du pilote que j'utilise.
public class CustomProjectAggregationOperation implements AggregationOperation {
private String jsonOperation;
public CustomProjectAggregationOperation(String jsonOperation) {
this.jsonOperation = jsonOperation;
}
@Override
public Document toDocument(AggregationOperationContext aggregationOperationContext) {
return aggregationOperationContext.getMappedObject(Document.parse(jsonOperation));
}
}
Maintenant que nous avons la possibilité de passer une requête JSON personnalisée dans notre implémentation mongodb spring, il ne reste plus qu'à brancher ces valeurs dans une requête TypedAggregation .
public List<FulfillmentChannel> getFulfillmentChannels(
String SOME_VARIABLE_STRING_1,
String SOME_VARIABLE_STRING_2) {
AggregationOperation match = Aggregation.match(
Criteria.where("dayOfWeek").is(SOME_VARIABLE_STRING_1));
AggregationOperation match2 = Aggregation.match(
Criteria.where("deliveryZipCodeTimings").ne(Collections.EMPTY_LIST));
String query =
"{ $lookup: { " +
"from: 'deliveryZipCodeTiming'," +
"let: { location_id: '$fulfillmentLocationId' }," +
"pipeline: [{" +
"$match: {$expr: {$and: [" +
"{ $eq: ['$fulfillmentLocationId', '$$location_id']}," +
"{ $eq: ['$zipCode', '" + SOME_VARIABLE_STRING_2 + "']}]}}}," +
"{ $project: { _id: 0, zipCode: 1, cutoffTime: 1 } }]," +
"as: 'deliveryZipCodeTimings'}}";
TypedAggregation<FulfillmentChannel> aggregation = Aggregation.newAggregation(
FulfillmentChannel.class,
match,
new CustomProjectAggregationOperation(query),
match2
);
AggregationResults<FulfillmentChannel> results =
mongoTemplate.aggregate(aggregation, FulfillmentChannel.class);
return results.getMappedResults();
}
Les pilotes sont à peu près toujours un peu en retard sur les fonctionnalités de langage actuelles fournies par MongoDB - par conséquent, certaines des dernières et meilleures fonctionnalités ne sont tout simplement pas bien accessibles via l'API. Je crains que ce soit l'un de ces cas et vous devrez recourir à l'utilisation de chaînes. Un peu comme ça (non testé):
AggregationOperation match = Aggregation.match(Criteria.where("dayOfWeek").is("SOME_VARIABLE_STRING_1"));
AggregationOperation match2 = Aggregation.match(Criteria.where("deliveryZipCodeTimings").ne([]));
String query = "{ $lookup: { from: 'deliveryZipCodeTiming', let: { location_id: '$fulfillmentLocationId' }, pipeline: [{ $match: { $expr: { $and: [ { $eq: ['$fulfillmentLocationId', '$$location_id']}, { $eq: ['$zipCode', 'SOME_VARIABLE_STRING_2']} ]} } }, { $project: { _id: 0, zipCode: 1, cutoffTime: 1 } }], as: 'deliveryZipCodeTimings' } }";
Aggregation.newAggregation(match, (DBObject) JSON.parse(query), match2);