如何使用 Micronaut 在 mongoDB 中创建 TextFree 搜索
How to create a TextFree search in mongoDB with 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()));
}
我认为这不是实现自由文本搜索的正确方法。
一开始你不需要 Flowable
和 List
或 Product
,因为 Flowable
可以管理多个值,这与 Single
不同。所以,有Flowable<Product>
就够了。然后你可以简单地 return 来自 find
方法的 Flowable
实例。
文本搜索可以这样实现:
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
。在控制器中,您可以直接 return 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"));
}
}
更新: 您可以通过在 logback.xml 中设置来调试与 MongoDB 的通信(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 CLI 中尝试,或者你可以安装 MongoDB Compass 在那里你可以更多地使用它并查看命令是否正确。
我正在使用响应式 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()));
}
我认为这不是实现自由文本搜索的正确方法。
一开始你不需要 Flowable
和 List
或 Product
,因为 Flowable
可以管理多个值,这与 Single
不同。所以,有Flowable<Product>
就够了。然后你可以简单地 return 来自 find
方法的 Flowable
实例。
文本搜索可以这样实现:
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
。在控制器中,您可以直接 return 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"));
}
}
更新: 您可以通过在 logback.xml 中设置来调试与 MongoDB 的通信(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 CLI 中尝试,或者你可以安装 MongoDB Compass 在那里你可以更多地使用它并查看命令是否正确。