Перевод «значения в столбце массива» запроса MongoDB в код данных Spring MongoDB - PullRequest
0 голосов
/ 06 февраля 2020

Как я могу перевести следующий запрос MongoDB в запрос Java на основе драйвера Java MongoDB Spring Data?

db.User.aggregate([
{ $match : { $expr: { $in: [ "ADMIN", "$roles" ] } } },
{ $sort : { "createdAt": 1 } },
{ $limit : 1 }
])

Мое попытанное решение в Kotlin, которое я считаю неправильным (я не знаю, как указать, что «роли» - это поле в пользовательском документе).

fun queryFirstAdmin(): User? {

    val matchRolesOpt = Aggregation.match(Criteria.where("ADMIN").`in`("roles"))
    val sortOpt = Aggregation.sort(Sort.Direction.ASC, "createdAt")
    val limitOpt = Aggregation.limit(1)
    var ops: MutableList<AggregationOperation> = mutableListOf()
    ops.add(matchRolesOpt)
    ops.add(sortOpt)
    ops.add(limitOpt)
    var aggregation = Aggregation.newAggregation(*ops.toTypedArray())
    val aggregationResult = mongoTemplate.aggregate(aggregation, User::class.java, User::class.java)
    return aggregationResult.uniqueMappedResult
}

Это решение работает, но, к сожалению, оно возвращает фрагмент документа пользователя (поскольку он был размотан):

fun queryFirstAdmin(): User? {
    val unwindOpt = Aggregation.unwind("roles")
    val matchRolesOpt = Aggregation.match(Criteria.where("roles").`is`("ADMIN"))
    val sortOpt = Aggregation.sort(Sort.Direction.ASC, "createdAt")
    val limitOpt = Aggregation.limit(1)
    var ops: MutableList<AggregationOperation> = mutableListOf(unwindOpt, matchRolesOpt, sortOpt, limitOpt)
    var aggregation = Aggregation.newAggregation(*ops.toTypedArray())
    val aggregationResult = mongoTemplate.aggregate(aggregation, User::class.java, User::class.java)
    return aggregationResult.uniqueMappedResult
}

, т. Е. Если возвращенный документ имеет массив ["ADMIN"], но исходный документ имеет ["ADMIN", "USER] в поле" роли "

Как это исправить?

1 Ответ

0 голосов
/ 06 февраля 2020

Код MongoDB Spring Java для агрегации:

MongoOperations mongoOps = new MongoTemplate(MongoClients.create(), "test");
Aggregation agg = newAggregation(
        match(where("roles").is("ADMIN")),
        sort(ASC, "createdAt"),
        limit(1L)
);
AggregationResults<Document> results = mongoOps.aggregate(agg, "User", Document.class);
results.forEach(System.out::println);


ПРИМЕЧАНИЕ:

Этап матча в совокупности

{ $match : { $expr: { $in: [ "ADMIN", "$roles" ] } } }

можно заменить на это, и результат будет таким же:

{ $match : { roles: "ADMIN" } }



Тот же запрос с использованием MongoDB Java Водитель :
Bson match = match(expr( Document.parse(" { $in: [ 'ADMIN', '$roles' ] } ")));
// -or- 
// Bson match = match(eq("roles", "ADMIN"));

List<Bson> pipeline = 
        Arrays.asList(match, sort(ascending("createdAt")), limit(1));

List<Document> results = new ArrayList<>();
collection.aggregate(pipeline).into(results); 

results.forEach(System.out::println);
...