Search code examples
reactive-programmingspring-data-couchbase

How to convert a n1ql query to use with Spring couchbase reactive repository alongwith @Query annotation?


I'm using Spring's reactive stack along with Spring's reactive couchbase to build api's and needing help in converting query which I want to use from ReactiveCouchbaseRepository.

approach for creating index in couchbase was taken from this post: 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);

query I am using to search is:

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

result of this query is:

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

I would like to use the same query from a method declared in a interface that is extending ReactiveCouchbaseRepository.

I have also tried the approach specified in this ticket: Can we Convert N1QL to shEL query for Spring use

This approach works fine but I want Spring to take care of boiler plate code and also noticed that calls are blocking but I would like to have non blocking calls towards couchbase.


Solution

  • I couldn't find the answer to my question but after trying few more options found that I can do this by changing the format of my JSON object.

    From:

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

    TO this:

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

    Now the method in the reactive couchbase repository is changed to:

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

    Further I checked the logs to see if thread is I/O thread or nio thread

    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"}
    
    

    I hope this solutions helps other as well and not sure why I wanted to the structure with Object and then array. Correct me if I am wrong.