#java #mongodb #hibernate #quarkus #quarkus-panache
#java #mongodb #спящий режим #quarkus #quarkus-panache
Вопрос:
У меня есть документы с массивами «тегов» в качестве свойств. Теперь я хочу запросить все отдельные элементы тегов.
{
"name": "test1",
"tags": ["tag1","tag2", "tag3"]
},
{
"name": "test2",
"tags": ["tag1"]
}
Решение в оболочке mongo:
db.ApiModel.distinct("tags")
что дает мне:
["tag1", "tag2", "tag3"]
Но как я могу добиться того же результата с помощью Panache? PanacheMongoEntity не предлагает конкретного метода distinct. Я также не знаю, как использовать этот find
метод для достижения моей цели или если это вообще возможно с помощью этого метода.
Все, о чем я мог подумать, это найти все теги с find("tags", "*")
помощью (является ли * подстановочным знаком?), А затем иметь дело с дубликатами в Java, но я не верю, что это предполагаемое использование.
Комментарии:
1. Я думаю, вы можете использовать
PanacheMongoEntityBase#stream
метод, который возвращает aStream<T>
, который, в свою очередь, может быть использован для получения ваших различных значений определенного поля ( Stream#distinct ).2. При переходе из спящего режима с SQL это выглядит как «плохой код», потому что я извлекаю все, а затем сужаю его. Но я думаю, что это правильный путь? Есть ли способ проверить запрос, который он создает в журналах?
Ответ №1:
Вы можете использовать любой из двух методов, чтобы получить distinct tags
из коллекции test
.
public List<String> getDistinctTags() {
return Tags
.<Tags>mongoCollection()
.distinct("tags", String.class)
.into(new ArrayList<String>());
}
public List<String> getDistinctTags() {
return Tags
.<Tags>streamAll()
.flatMap(e -> e.tags.stream())
.distinct()
.collect(toList());
}
Предполагая Tags
, что класс определен следующим образом и представляет объект Panache:
@MongoEntity(collection="test")
public class Tags extends PanacheMongoEntity {
public String name;
public List<String> tags;
// ...
}
Комментарии:
1. Спасибо! Значит, сам запрос выполняется только тогда, когда я вызываю .collect()? Потому что в противном случае streamAll () (он извлекает каждый документ в моей коллекции?) будет выполняться сначала, и я получаю все, а затем использую distinct в java, а не в mongodb? Или я думаю, что слишком ориентирован на SQL?
2. Хорошо, речь идет о втором методе
getDistinctTags()
. Запрос фактически извлекает все документы как ajava.util.stream.Stream
, к которым применяются методы StreamflatMap
distinct
иcollect
. В первомgetDistinctTags()
случае distinct применяется на сервере, и результаты возвращаются.3.
PanacheMongoEntity.streamAll
Возвращает aStream
со всеми объектами типа.4. Итак, первое решение было бы более эффективным с точки зрения производительности, верно? Я только что пришел из мира SQL и извлекаю всю таблицу, а затем выполняю операции с ней на java, что было бы плохой практикой.
5. Запрос distinct выполняется на сервере, и вы получаете результат операции в своем Java-приложении. Да, запрос, выполняемый на сервере, более эффективен, и вы можете увидеть прирост производительности, основанный на ваших данных и других факторах, таких как сеть и т.д..