如何将n1ql查询转换为与Spring couchbase反应式存储库以及@Query注释一起使用?

时间:2019-04-18 13:47:43

标签: reactive-programming spring-data-couchbase

我正在使用Spring的反应式堆栈以及Spring的反应式榻榻米来构建api,并且需要帮助来转换要从ReactiveCouchbaseRepository使用的查询。

在couchbase中创建索引的方法摘自以下文章: https://forums.couchbase.com/t/indexing-array-of-strings/14977

CREATE INDEX idx_emaillist ON api (DISTINCT ARRAY k FOR k IN emails.emaillist END);
我用来搜索的

查询是:

SELECT * FROM user AS u WHERE ANY k IN u.emails.emaillist SATISFIES k = "abc@email.com" END;

此查询的结果是:

[
  {
    "u": {
      "_class": "com.users.api.model.User",
      "name": "abc",
      "emails": {
        "emaillist": [
          "abc@email.com",
          ""xyz@email.com"
        ]
      }
    }
  }
]

我想在扩展ReactiveCouchbaseRepository的接口中声明的方法中使用相同的查询。

我还尝试了此票证中指定的方法: Can we Convert N1QL to shEL query for Spring use

这种方法效果很好,但我希望Spring处理样板代码,并且还注意到调用正在阻塞,但我希望对沙发床的调用是非阻塞的。

2 个答案:

答案 0 :(得分:1)

如果您没有与电子邮件相关的任何其他属性,那么按照实际操作存储它是一种更好的方法:

[
  {
    "u": {
      "_class": "com.users.api.model.User",
      "name": "abc",
      "emails": [
          "abc@email.com",
          ""xyz@email.com"
      ]
    }
  }
]

请注意,您还必须更改索引。

有关如何为数组创建索引的一些很好的链接: https://docs.couchbase.com/server/6.0/n1ql/n1ql-language-reference/indexing-arrays.html https://forums.couchbase.com/t/how-to-correctly-create-array-index/17349 https://blog.couchbase.com/making-the-most-of-your-arrays-with-array-indexing/

您可以打印由spring数据生成的查询: https://blog.couchbase.com/how-to-log-queries-generated-by-spring-data/

并使用“ EXPLAIN”关键字运行查询,以确保您的查询正在使用索引。如果您使用的是企业版,则只需检查查询计划器即可。

答案 1 :(得分:0)

我找不到我的问题的答案,但是在尝试了更多选择之后,发现可以通过更改JSON对象的格式来做到这一点。

发件人:

[
  {
    "u": {
      "_class": "com.users.api.model.User",
      "name": "abc",
      "emails": {
        "emaillist": [
          "abc@email.com",
          ""xyz@email.com"
        ]
      }
    }
  }
]

对此:

[
  {
    "u": {
      "_class": "com.users.api.model.User",
      "name": "abc",
      "emails": [
          "abc@email.com",
          ""xyz@email.com"
      ]
    }
  }
]

现在,反应式榻榻米知识库中的方法已更改为:

    @Query("#{#n1ql.selectEntity} where #{#n1ql.filter} AND ARRAY_CONTAINS(emails, $1)")
    Flux<User> findByIdEmail(String email);

我还检查了日志以查看线程是I / O线程还是nio线程

DEBUG 19228 --- [reactor-http-nio-3] s.d.c.r.q.ReactiveAbstractN1qlBasedQuery : Executing N1QL query: {"args":["ABC"],"statement":"SELECT META(`user`).id AS _ID, META(`user`).cas AS _CAS, `user`.* FROM `user` where `_class` = \"com.users.api.model.User\" AND ARRAY_CONTAINS(emails, $1)","scan_consistency":"statement_plus"}

我希望这个解决方案也能对其他人有所帮助,并且不确定为什么要使用Object然后使用array进行结构化。 如果我错了请纠正我。