Как создать текстовый поиск в mongoDB с помощью Micronaut

Я использую реактивный MongoDb и пытаюсь реализовать поиск свободного текста на основе веса

implementation("io.micronaut.mongodb:micronaut-mongo-reactive")

ниже POJO

public class Product {
    @BsonProperty("_id")
    @BsonId
    private ObjectId id;
    private String name;
    private float price;
    private String description;
}

Пробовал этот простой пример

public Flowable<List<Product>> findByFreeText(String text) {
    LOG.info(String.format("Listener --> Listening value = %s", text));
    Flowable.fromPublisher(this.repository.getCollection("product", List.class)
            .find(new Document("$text", new Document("$search", text)
                    .append("$caseSensitive", false)
                    .append("$diacriticSensitive", false)))).subscribe(item -> {
                System.out.println(item);
            }, error -> {
                System.out.println(error);
            });
    return Flowable.just(List.of(new Product()));
}

Я не думаю, что это правильный способ реализации поиска по произвольному тексту.


person San Jaisy    schedule 01.11.2020    source источник


Ответы (1)


Сначала вам не нужно иметь Flowable с List из Product, потому что Flowable может управлять более чем одним значением, в отличие от Single. Итак, достаточно Flowable<Product>. Затем вы можете просто вернуть экземпляр Flowable из метода find.

Текстовый поиск может быть реализован следующим образом:

public Flowable<Product> findByFreeText(final String query) {
    return Flowable.fromPublisher(repository.getCollection("product", Product.class)
        .find(new Document("$text",
            new Document("$search", query)
                .append("$caseSensitive", false)
                .append("$diacriticSensitive", false)
        )));
}

Затем потребителю метода решать, как он подписывается на результат Flowable. В контроллере вы можете напрямую вернуть экземпляр Flowable. Если вам нужно использовать это где-то в вашем коде, вы можете использовать subscribe() или blockingSubscribe() и так далее.

И вы, конечно, можете протестировать это с помощью JUnit следующим образом:

@MicronautTest
class SomeServiceTest {
    @Inject
    SomeService service;

    @Test
    void findByFreeText() {
        service.findByFreeText("test")
            .test()
            .awaitCount(1)
            .assertNoErrors()
            .assertValue(p -> p.getName().contains("test"));
    }
}

Обновление: вы можете отладить обмен данными с MongoDB, установив это в logback.xml (Micronaut использует Logback в качестве среды ведения журнала по умолчанию), в файле конфигурации журнала:

<configuration>
    ....
    <logger name="org.mongodb" level="debug"/>
</configuration>

Тогда вы увидите это в файле журнала:

16:20:21.257 [Thread-5] DEBUG org.mongodb.driver.protocol.command - Sending command '{"find": "product", "filter": {"$text": {"$search": "test", "$caseSensitive": false, "$diacriticSensitive": false}}, "batchSize": 2147483647, "$db": "some-database"}' with request id 6 to database some-database on connection [connectionId{localValue:3, serverValue:1634}] to server localhost:27017
16:20:21.258 [Thread-8] DEBUG org.mongodb.driver.protocol.command - 16:20:21.258 [Thread-7] DEBUG org.mongodb.driver.protocol.command - Execution of command with request id 6 completed successfully in 2.11 ms on connection [connectionId{localValue:3, serverValue:1634}] to server localhost:27017

Затем вы можете скопировать команду из журнала и попробовать ее в командной строке MongoDB или установить MongoDB Compass. где вы можете поиграть с этим еще и посмотреть, верна ли команда или нет.

person cgrim    schedule 01.11.2020
comment
Любая идея, как мне установить регистратор для mongoDb в микронавте ?? У меня поиск не работает? Я обновил код - person San Jaisy; 01.11.2020
comment
Есть ли возможность добавить в файл application.yml? - person San Jaisy; 01.11.2020
comment
Не могли бы вы также помочь мне с этим stackoverflow.com/questions/64247414/ Я так долго борюсь - person San Jaisy; 01.11.2020
comment
Добавьте регистратор в файл logback.xml, как описано в ответе, и просмотрите файл журнала. Затем вы можете попробовать ту же команду в MongoDB CLI или установить MongoDB Compass, где вы сможете играть с этим еще и посмотрите, верна ли команда. Вы действительно храните List<Product> в коллекции Mongo? Разве это не собрание Product? - person cgrim; 02.11.2020
comment
Да, это коллекция продуктов. - person San Jaisy; 02.11.2020
comment
спасибо, что он работает, не могли бы вы помочь мне вернуть значение в производителе kafka от слушателя, как описано в этом вопросе stackoverflow.com/questions/64247414/ - person San Jaisy; 02.11.2020
comment
У меня еще нет опыта работы с Kafka, но я посмотрю в ближайшие дни ;-) - person cgrim; 02.11.2020
comment
Спасибо за поддержку - person San Jaisy; 02.11.2020