{"id":2871,"date":"2017-03-01T08:46:35","date_gmt":"2017-03-01T16:46:35","guid":{"rendered":"https:\/\/www.couchbase.com\/blog\/?p=2871"},"modified":"2025-06-13T20:28:13","modified_gmt":"2025-06-14T03:28:13","slug":"using-couchbase-full-text-search-service-java","status":"publish","type":"post","link":"https:\/\/www.couchbase.com\/blog\/ko\/using-couchbase-full-text-search-service-java\/","title":{"rendered":"Java\uc5d0\uc11c Couchbase \uc804\uccb4 \ud14d\uc2a4\ud2b8 \uac80\uc0c9 \uc11c\ube44\uc2a4 \uc0ac\uc6a9"},"content":{"rendered":"<p><em><a href=\"https:\/\/www.linkedin.com\/in\/ratnopam-chakrabarti\" target=\"_blank\" rel=\"noopener\">Ratnopam Chakrabarti<\/a><\/em><em>\u00a0is a software developer currently working for Ericsson Inc. He has been focused on IoT, machine-to-machine technologies, connected cars, and smart city domains for quite a while. He loves learning new technologies and putting them to work. When he\u2019s not working, he enjoys spending time with his 3-year-old son.<\/em><\/p>\n<p>Full-text based search is a feature that allows users to search based on texts and keywords, and is very popular among users and the developer community. So it\u2019s a no-brainer that there are lots of APIs and frameworks that offer full-text search, including Apache Solr, Lucene, and Elasticsearch, just to name a few. <a href=\"https:\/\/developer.couchbase.com\/documentation\/server\/current\/fts\/full-text-intro.html\">Couchbase<\/a>, one of the leading NoSQL giants, started rolling out this feature in their Couchbase Server 4.5 release.<\/p>\n<p>In this post, I am going to describe how to integrate the full-text search service into their application using the <a href=\"https:\/\/developer.couchbase.com\/documentation\/server\/current\/sdk\/java\/start-using-sdk.html\">Couchbase Java SDK<\/a>.<\/p>\n<h4>Set Up<\/h4>\n<p>Go to start.spring.io and select Couchbase as a dependency into your Spring boot application.<\/p>\n<p>Once you have the project set up, you should see the following dependency in your project object model (pom.xml) file. It ensures that all Couchbase libraries are in place for the app.<\/p>\n<p>&lt;dependency&gt;<\/p>\n<p>&lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;<\/p>\n<p>&lt;artifactId&gt;spring-boot-starter-data-couchbase&lt;\/artifactId&gt;<\/p>\n<p>&lt;\/dependency&gt;<\/p>\n<p>You need to set up a Couchbase bucket to house your sample dataset to search on.<\/p>\n<p>I have created a bucket named \u201cconference\u201d in the Couchbase admin console.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2017\/02\/pasted-image-0.png\" alt=\"Couchbase admin console\" width=\"1139\" height=\"374\" \/><\/p>\n<p>The \u201cconference\u201d bucket has three documents currently, and they hold data about different conferences held across the world. You can extend this data model or create your own if you would like to experiment. For instance, r\u00e9sum\u00e9s, product catalogs, or even tweets make a good use case for full-text search. For case in point though, let\u2019s stick to the conference data as shown below:<\/p>\n<p><code><br \/>\n{<\/code><\/p>\n<p>&#8220;title&#8221;: &#8220;DockerCon&#8221;,<\/p>\n<p>&#8220;type&#8221;: &#8220;Conference&#8221;,<\/p>\n<p>&#8220;location&#8221;: &#8220;Austin&#8221;,<\/p>\n<p>&#8220;start&#8221;: &#8220;04\/17\/2017&#8221;,<\/p>\n<p>&#8220;end&#8221;: &#8220;04\/20\/2017&#8221;,<\/p>\n<p>&#8220;topics&#8221;: [<\/p>\n<p>&#8220;containers&#8221;,<\/p>\n<p>&#8220;devops&#8221;,<\/p>\n<p>&#8220;microservices&#8221;,<\/p>\n<p>&#8220;product development&#8221;,<\/p>\n<p>&#8220;virtualization&#8221;<\/p>\n<p>],<\/p>\n<p>&#8220;attendees&#8221;: 20000,<\/p>\n<p>&#8220;summary&#8221;: &#8220;DockerCon will feature topics and content covering all aspects of Docker and it&#8217;s ecosystem and will be suitable for Developers, DevOps, System Administrators and C-level executives&#8221;,<\/p>\n<p>&#8220;social&#8221;: {<\/p>\n<p>&#8220;facebook&#8221;: &#8220;https:\/\/www.facebook.com\/dockercon&#8221;,<\/p>\n<p>&#8220;twitter&#8221;: &#8220;https:\/\/www.twitter.com\/dockercon&#8221;<\/p>\n<p>},<\/p>\n<p>&#8220;speakers&#8221;: [<\/p>\n<p>{<\/p>\n<p>&#8220;name&#8221;: &#8220;Arun Gupta&#8221;,<\/p>\n<p>&#8220;talk&#8221;: &#8220;Docker with couchbase&#8221;,<\/p>\n<p>&#8220;date&#8221;: &#8220;04\/18\/2017&#8221;,<\/p>\n<p>&#8220;duration&#8221;: &#8220;2&#8221;<\/p>\n<p>},<\/p>\n<p>{<\/p>\n<p>&#8220;name&#8221;: &#8220;Laura Frank&#8221;,<\/p>\n<p>&#8220;talk&#8221;: &#8220;Opensource&#8221;,<\/p>\n<p>&#8220;date&#8221;: &#8220;04\/19\/2017&#8221;,<\/p>\n<p>&#8220;duration&#8221;: &#8220;2&#8221;<\/p>\n<p>}<\/p>\n<p>]<\/p>\n<p>}<\/p>\n<p>In order to use full-text search on the above dataset, you need to create a full-text search index first. Do the following steps:<\/p>\n<p>In the Couchbase admin console, click on the Indexes tab.<\/p>\n<p>Click on the Full Text link, which will list the current full text indexes.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2017\/02\/pasted-image-0-4.png\" alt=\"text indexes Image\" width=\"1160\" height=\"288\" \/><\/p>\n<p>As you can guess, I have created an index named \u201cconference-search\u201d which I would use from the Java code to search the conference-related data.<\/p>\n<p>Click on the New Full Text Index button to create a new index.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2017\/02\/pasted-image-0-1.png\" alt=\"pasted image 0 1\" \/><\/p>\n<p>Yes, it\u2019s that easy. Once you have created the index, you are ready to use the index from the app you are building.<\/p>\n<p>Before we dive into the code, let\u2019s have a look at the other two documents that are already in the bucket.<\/p>\n<p><code><br \/>\nConference::2<\/code><\/p>\n<p>{<\/p>\n<p>&#8220;title&#8221;: &#8220;Devoxx UK&#8221;,<\/p>\n<p>&#8220;type&#8221;: &#8220;Conference&#8221;,<\/p>\n<p>&#8220;location&#8221;: &#8220;Belgium&#8221;,<\/p>\n<p>&#8220;start&#8221;: &#8220;05\/11\/2017&#8221;,<\/p>\n<p>&#8220;end&#8221;: &#8220;05\/12\/2017&#8221;,<\/p>\n<p>&#8220;topics&#8221;: [<\/p>\n<p>&#8220;cloud&#8221;,<\/p>\n<p>&#8220;iot&#8221;,<\/p>\n<p>&#8220;big data&#8221;,<\/p>\n<p>&#8220;machine learning&#8221;,<\/p>\n<p>&#8220;virtual reality&#8221;<\/p>\n<p>],<\/p>\n<p>&#8220;attendees&#8221;: 10000,<\/p>\n<p>&#8220;summary&#8221;: &#8220;Devoxx UK returns to London in 2017. Once again we will welcome amazing speakers and attendees for the very best developer content and awesome experiences&#8221;,<\/p>\n<p>&#8220;social&#8221;: {<\/p>\n<p>&#8220;facebook&#8221;: &#8220;https:\/\/www.facebook.com\/devoxxUK&#8221;,<\/p>\n<p>&#8220;twitter&#8221;: &#8220;https:\/\/www.twitter.com\/devoxxUK&#8221;<\/p>\n<p>},<\/p>\n<p>&#8220;speakers&#8221;: [<\/p>\n<p>{<\/p>\n<p>&#8220;name&#8221;: &#8220;Viktor Farcic&#8221;,<\/p>\n<p>&#8220;talk&#8221;: &#8220;Cloudbees&#8221;,<\/p>\n<p>&#8220;date&#8221;: &#8220;05\/11\/2017&#8221;,<\/p>\n<p>&#8220;duration&#8221;: &#8220;2&#8221;<\/p>\n<p>},<\/p>\n<p>{<\/p>\n<p>&#8220;name&#8221;: &#8220;Patrick Kua&#8221;,<\/p>\n<p>&#8220;talk&#8221;: &#8220;Thoughtworks&#8221;,<\/p>\n<p>&#8220;date&#8221;: &#8220;05\/12\/2017&#8221;,<\/p>\n<p>&#8220;duration&#8221;: &#8220;2&#8221;<\/p>\n<p>}<\/p>\n<p>]<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>Conference::3<\/p>\n<p>{<\/p>\n<p>&#8220;title&#8221;: &#8220;ReInvent&#8221;,<\/p>\n<p>&#8220;type&#8221;: &#8220;Conference&#8221;,<\/p>\n<p>&#8220;location&#8221;: &#8220;Las Vegas&#8221;,<\/p>\n<p>&#8220;start&#8221;: &#8220;11\/28\/2017&#8221;,<\/p>\n<p>&#8220;end&#8221;: &#8220;11\/30\/2017&#8221;,<\/p>\n<p>&#8220;topics&#8221;: [<\/p>\n<p>&#8220;aws&#8221;,<\/p>\n<p>&#8220;serverless&#8221;,<\/p>\n<p>&#8220;microservices&#8221;,<\/p>\n<p>&#8220;cloud computing&#8221;,<\/p>\n<p>&#8220;augmented reality&#8221;<\/p>\n<p>],<\/p>\n<p>&#8220;attendees&#8221;: 30000,<\/p>\n<p>&#8220;summary&#8221;: &#8220;Aamazon web services reInvent 2017 promises a larger venue, more sessions and a focus on technologies like microservices and Lambda.&#8221;,<\/p>\n<p>&#8220;social&#8221;: {<\/p>\n<p>&#8220;facebook&#8221;: &#8220;https:\/\/www.facebook.com\/reinvent&#8221;,<\/p>\n<p>&#8220;twitter&#8221;: &#8220;https:\/\/www.twitter.com\/reinvent&#8221;<\/p>\n<p>},<\/p>\n<p>&#8220;speakers&#8221;: [<\/p>\n<p>{<\/p>\n<p>&#8220;name&#8221;: &#8220;Ryan K&#8221;,<\/p>\n<p>&#8220;talk&#8221;: &#8220;Amazon Alexa&#8221;,<\/p>\n<p>&#8220;date&#8221;: &#8220;11\/28\/2017&#8221;,<\/p>\n<p>&#8220;duration&#8221;: &#8220;2.5&#8221;<\/p>\n<p>},<\/p>\n<p>{<\/p>\n<p>&#8220;name&#8221;: &#8220;Anthony J&#8221;,<\/p>\n<p>&#8220;talk&#8221;: &#8220;Lambda&#8221;,<\/p>\n<p>&#8220;date&#8221;: &#8220;11\/29\/2017&#8221;,<\/p>\n<p>&#8220;duration&#8221;: &#8220;1.5&#8221;<\/p>\n<p>}<\/p>\n<p>]<\/p>\n<p>}<\/p>\n<h4>Invoking Full-Text Search from Java Code<\/h4>\n<h5>Connect to Couchbase bucket from code<\/h5>\n<p>Spring boot offers a convenient way to connect to the Couchbase environment by allowing us to specify certain Couchbase environment details as a Spring configuration. We normally specify the following parameters in the application.properties file:<\/p>\n<p>spring.couchbase.bootstrap-hosts=127.0.0.1<br \/>\nspring.couchbase.bucket.name=conference<br \/>\nspring.couchbase.bucket.password=<\/p>\n<p>Here, I have specified my localhost ip since I am running Couchbase Server on my laptop. Note: You can run Couchbase as a Docker container by providing the IP address of the container.<\/p>\n<p>The bucket-name has to match with the name of the bucket created using the Couchbase console.<\/p>\n<p>We can also specify a cluster of IP\u00a0addresses as bootstrap-hosts. Spring will provide a Couchbase environment cluster with all the nodes running Couchbase on them. If a password was set up when the bucket was created, then we can specify that as well; otherwise,\u00a0leave that field empty.\u00a0In our case,\u00a0we leave it empty.<\/p>\n<p>In order to run query against our desired bucket, first we need to have a reference to the bucket object. And the spring-couchbase configuration does all the heavy lifting behind the scenes for us. All we have to do is inject the bucket from the constructor within the Spring service bean class.<\/p>\n<p>Here is the code:<\/p>\n<p><code><br \/>\n@Service<\/code><\/p>\n<p>public class FullTextSearchService {<\/p>\n<p>private Bucket bucket;<\/p>\n<p>public FullTextSearchService(Bucket bucket) {<\/p>\n<p>this.bucket = bucket;<\/p>\n<p>log.info(&#8220;******** Bucket :: = &#8221; + bucket.name());<\/p>\n<p>}<\/p>\n<p>public void findByTextMatch(String searchText) throws Exception {<\/p>\n<p>SearchQueryResult result = getBucket().query(<\/p>\n<p>new SearchQuery(FtsConstants.FTS_IDX_CONF, SearchQuery.matchPhrase(searchText)).fields(&#8220;summary&#8221;));<\/p>\n<p>for (SearchQueryRow hit : result.hits()) {<\/p>\n<p>log.info(&#8220;****** score := &#8221; + hit.score() + &#8221; and content := &#8221;<\/p>\n<p>+ bucket.get(hit.id()).content().get(&#8220;title&#8221;));<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>We can also customize some of the CouchbaseEnvironment settings parameters. For a detailed list of parameters we can customize, take a look at the following <a href=\"https:\/\/docs.spring.io\/spring-boot\/docs\/current\/reference\/html\/boot-features-nosql.html\">reference guidelines<\/a>:<\/p>\n<p>At this point, we can invoke the service from the <em>CommandLineRunner <\/em>bean.<\/p>\n<p><code><br \/>\n@Configuration<\/code><\/p>\n<p>public class FtsRunner implements CommandLineRunner {<\/p>\n<p>@Autowired<\/p>\n<p>FullTextSearchService fts;<\/p>\n<p>@Override<\/p>\n<p>public void run(String&#8230; arg0) throws Exception {<\/p>\n<p>fts.findByTextMatch(&#8220;developer&#8221;);<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<h5>Using Full-Text\u00a0Search Service<\/h5>\n<p>At the core of the Java\u00a0SDK, Couchbase offers <em>query()<\/em>\u00a0method as a way querying on a specified bucket. If you are familiar with N1QL Query or View\u00a0Query, then the <em>query() <\/em>method offers a similar pattern; the only difference for Search is that it accepts a <em>SearchQuery <\/em>parameter as an argument.<\/p>\n<p>Following is the code that searches for a given text in the \u201cconference\u201d bucket. <em>getBucket() <\/em>method returns a handle of the bucket.<\/p>\n<p>When creating a SearchQuery, you need to supply the name of the index that you created in the Set\u00a0Up section above. Here, I am using \u201cconference-search\u201d as the index which is specified in the FtsConstants.FTS_IDX_CONF. By the way, the full source code of the app is uploaded in GitHub and available for download. The link is at the end of the post.<\/p>\n<p><code><br \/>\npublic static void findByTextMatch(String searchText) throws Exception {<\/code><\/p>\n<p>SearchQueryResult result = getBucket().query(new \u00a0 \u00a0SearchQuery(FtsConstants.FTS_IDX_CONF, SearchQuery.matchPhrase(searchText)).fields(&#8220;summary&#8221;));<\/p>\n<p>log.info(&#8220;****** total \u00a0hits := &#8220;+ result.hits().size());<\/p>\n<p>for (SearchQueryRow hit : result.hits()) {<\/p>\n<p>log.info(&#8220;****** score := &#8221; + hit.score() + &#8221; and content := &#8220;+ bucket.get(hit.id()).content().get(&#8220;title&#8221;));<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>The above code is searching on the \u201csummary\u201d field of the documents in the bucket by using the <em>matchPhrase(searchText) <\/em>method.<\/p>\n<p>The code is invoked by a simple call:<\/p>\n<p><em>findByTextMatch(&#8220;developer&#8221;);<\/em><\/p>\n<p>So, the full-text search should return all documents in the conference bucket that have the text \u201cdeveloper\u201d in their summary field. Here\u2019s the output:<\/p>\n<p>Opened bucket conference<\/p>\n<p>****** total \u00a0hits := 1<\/p>\n<p>****** score := 0.036940739161339185 and content := Devoxx UK<\/p>\n<p>The total hits represent the total number of matches found. Here it\u2019s 1 and the corresponding scoring of that match can also be found. The code doesn\u2019t print the entire document, just outputs the conference title. You can print the other attributes of the document if you wish to.<\/p>\n<p>There are other ways\u00a0of using the SearchQuery which are discussed next.<\/p>\n<h4>Fuzzy Text Search<\/h4>\n<p>You can perform fuzzy query by specifying a maximum <u><a href=\"https:\/\/en.wikipedia.org\/wiki\/Levenshtein_distance\" target=\"_blank\" rel=\"noopener\">Levenshtein distance<\/a><\/u>\u00a0as the maximum fuzziness() to allow on the term. The default fuzziness is 2.<\/p>\n<p>For example, let\u2019s say I want to find the conference where \u201csysops\u201d is one of the \u201ctopics\u201d. From the dataset above, you can see there\u2019s no \u201csysops\u201d topics present in any of the conferences. The closest match is \u201cdevops\u201d; however,\u00a0that is 3 Levenshtein distance away. So,\u00a0if I run the following code with fuzziness 1 or 2 it shouldn\u2019t bring back any result,\u00a0which it doesn\u2019t.<\/p>\n<p><code><br \/>\nSearchQueryResult resultFuzzy = getBucket().query(new SearchQuery(FtsConstants.FTS_IDX_CONF, SearchQuery.match(searchText).fuzziness(<strong>2<\/strong>)).fields(\"topics\"));<\/code><\/p>\n<p>log.info(&#8220;****** total \u00a0hits := &#8220;+ resultFuzzy.hits().size());<\/p>\n<p>for (SearchQueryRow hit : resultFuzzy.hits()) {<\/p>\n<p>log.info(&#8220;****** score := &#8221; + hit.score() + &#8221; and content := &#8220;+ bucket.get(hit.id()).content().get(&#8220;topics&#8221;));<\/p>\n<p>}<\/p>\n<p>findByTextFuzzy(&#8220;sysops&#8221;); gives the following output:<\/p>\n<p><strong>total \u00a0hits := 0<\/strong><\/p>\n<p>Now, if I change the fuzziness to \u201c3\u201d and invoke the same code again, I get a document back. Here goes:<\/p>\n<p><strong>\u00a0****** total \u00a0hits := 1<\/strong><\/p>\n<p>****** score := 0.016616112953992054 and content := [&#8220;containers&#8221;,&#8221;<strong>devops<\/strong>&#8220;,&#8221;microservices&#8221;,&#8221;product development&#8221;,&#8221;virtualization&#8221;]<\/p>\n<p>Since \u201cdevops\u201d matches \u201csysops\u201d with a fuzziness of 3, the search is able to find the document.<\/p>\n<h4>Regular Expression Query<\/h4>\n<p>You can do regular expression-based queries using SearchQuery. The following code makes use of the <em>RegExpQuery <\/em>to search on \u201ctopics\u201d based on a supplied pattern.<br \/>\n<code><br \/>\nRegexpQuery rq = new RegexpQuery(regexp).field(\"topics\");<\/code><\/p>\n<p>SearchQueryResult resultRegExp = getBucket().query(new SearchQuery(FtsConstants.FTS_IDX_CONF, rq));<\/p>\n<p>log.info(&#8220;****** total \u00a0hits := &#8220;+ resultRegExp.hits().size());<\/p>\n<p>for (SearchQueryRow hit : resultRegExp.hits()) {<\/p>\n<p>log.info(&#8220;****** score := &#8221; + hit.score() + &#8221; and content := &#8220;+ bucket.get(hit.id()).content().get(&#8220;topics&#8221;));<\/p>\n<p>}<\/p>\n<p>When invoked as<\/p>\n<p>findByRegExp(&#8220;[a-z]*\\\\s*reality&#8221;);<\/p>\n<p>It returns the following 2 documents:<\/p>\n<p><strong>****** total \u00a0hits := 2<\/strong><\/p>\n<p>****** score := 0.11597946228887497 and content := [&#8220;aws&#8221;,&#8221;serverless&#8221;,&#8221;microservices&#8221;,&#8221;cloud computing&#8221;,&#8221;<strong>augmented reality<\/strong>&#8220;]<\/p>\n<p>****** score := 0.1084888528694293 and content := [&#8220;cloud&#8221;,&#8221;iot&#8221;,&#8221;big data&#8221;,&#8221;machine learning&#8221;,&#8221;<strong>virtual reality<\/strong>&#8220;]<\/p>\n<h4>Querying by Prefix<\/h4>\n<p>Couchbase enables you to query based on a \u201cprefix\u201d of a text element. The API searches for texts that start with the specified prefix. The code is simple to use; it searches on the \u201csummary\u201d field of the document for the texts that have the supplied prefix.<\/p>\n<p><code><br \/>\nPrefixQuery pq = new PrefixQuery(prefix).field(\"summary\");<\/code><\/p>\n<p>SearchQueryResult resultPrefix = getBucket().query(new SearchQuery(FtsConstants.FTS_IDX_CONF, pq).fields(&#8220;summary&#8221;));<\/p>\n<p>log.info(&#8220;****** total \u00a0hits := &#8220;+ resultPrefix.hits().size());<\/p>\n<p>for (SearchQueryRow hit : resultPrefix.hits()) {<\/p>\n<p>log.info(&#8220;****** score := &#8221; + hit.score() + &#8221; and content := &#8220;+ bucket.get(hit.id()).content().get(&#8220;summary&#8221;));<\/p>\n<p>}<\/p>\n<p>If you invoke the code as findByPrefix(&#8220;micro&#8221;);<\/p>\n<p>You get the following output:<\/p>\n<p><strong>\u00a0****** total \u00a0hits := 1<\/strong><\/p>\n<p>****** score := 0.08200986407165835 and content := Aamazon web services reInvent 2017 promises a larger venue, more sessions and a focus on technologies like <strong>microservices<\/strong>\u00a0and Lambda.<\/p>\n<h4>Query by Phrase<\/h4>\n<p>The following code lets you query a phrase in a text.<\/p>\n<p><code><br \/>\nMatchPhraseQuery mpq = new MatchPhraseQuery(matchPhrase).field(\"speakers.talk\");<\/code><\/p>\n<p>SearchQueryResult resultPrefix = getBucket().query(new SearchQuery(FtsConstants.FTS_IDX_CONF, mpq).fields(&#8220;speakers.talk&#8221;));<\/p>\n<p>log.info(&#8220;****** total \u00a0hits := &#8220;+ resultPrefix.hits().size());<\/p>\n<p>for (SearchQueryRow hit : resultPrefix.hits()) {<\/p>\n<p>log.info(&#8220;****** score := &#8221; + hit.score() + &#8221; and content := &#8220;+ bucket.get(hit.id()).content().get(&#8220;title&#8221;) + &#8221; speakers = &#8220;+bucket.get(hit.id()).content().get(&#8220;speakers&#8221;));<\/p>\n<p>}<\/p>\n<p>Here, the query is looking for a phrase in\u00a0the\u00a0\u201cspeakers.talk\u201d field and returns the match if found.<\/p>\n<p>A sample invocation of the above code with<\/p>\n<p>findByMatchPhrase(&#8220;Docker with couchbase&#8221;) gives the following expected output:<\/p>\n<p><strong>****** total \u00a0hits := 1<\/strong><\/p>\n<p>****** score := 0.25054427342401087 and content := DockerCon speakers = [{&#8220;duration&#8221;:&#8221;2&#8243;,&#8221;date&#8221;:&#8221;04\/18\/2017&#8243;,&#8221;talk&#8221;:&#8221;<strong>Docker with couchbase<\/strong>&#8220;,&#8221;name&#8221;:&#8221;Arun Gupta&#8221;},{&#8220;duration&#8221;:&#8221;2&#8243;,&#8221;date&#8221;:&#8221;04\/19\/2017&#8243;,&#8221;talk&#8221;:&#8221;Opensource&#8221;,&#8221;name&#8221;:&#8221;Laura Frank&#8221;}]<\/p>\n<h4>Range Query<\/h4>\n<p>Full-ext search is also pretty useful when it comes to range-based searching \u2013 be it a numeric range or even a date range. For example, if you want to find out the conference(s) where the number of attendees fall within a range, you can easily do that by,<\/p>\n<p>findByNumberRange(5000, 30000);<\/p>\n<p>Here, the first argument is the min of the range and the second argument is the max of the range.<\/p>\n<p>Here\u2019s the code that gets triggered:<\/p>\n<p><code><br \/>\nNumericRangeQuery nrq = new NumericRangeQuery().min(min).max(max).field(\"attendees\");<\/code><\/p>\n<p>SearchQueryResult resultPrefix = getBucket().query(new SearchQuery(FtsConstants.FTS_IDX_CONF, nrq).fields(&#8220;title&#8221;, &#8220;attendees&#8221;, &#8220;location&#8221;));<\/p>\n<p>log.info(&#8220;****** total \u00a0hits := &#8220;+ resultPrefix.hits().size());<\/p>\n<p>for (SearchQueryRow hit : resultPrefix.hits()) {<\/p>\n<p>JsonDocument row = bucket.get(hit.id());<\/p>\n<p>log.info(&#8220;****** score := &#8221; + hit.score() + &#8221; and title := &#8220;+ row.content().get(&#8220;title&#8221;) + &#8221; attendees := &#8220;+ row.content().get(&#8220;attendees&#8221;) + &#8221; location := &#8221; + row.content().get(&#8220;location&#8221;));<\/p>\n<p>}<\/p>\n<p>And it gives the following output\u00a0\u2013\u00a0the conferences that have attendees falling between the supplied range are returned.<\/p>\n<p><strong>\u00a0****** total \u00a0hits := 2<\/strong><\/p>\n<p>****** score := 5.513997563179222E-5 and title := <strong>DockerCon attendees := 20000<\/strong>\u00a0location := Austin<\/p>\n<p>****** score := 5.513997563179222E-5 and title := <strong>Devoxx UK attendees := 10000<\/strong>\u00a0location := Belgium<\/p>\n<h4>Combination Query<\/h4>\n<p>Couchbase full-text search service allows you to use a combination of queries according to your need. To demonstrate this, let\u2019s first invoke the API by supplying two arguments.<\/p>\n<p>findByMatchCombination(&#8220;aws&#8221;, &#8220;containers&#8221;);<\/p>\n<p>Here, the client code is trying to use the combination search based on \u201caws\u201d and \u201ccontainers\u201d. Let\u2019s look at the query API now.<\/p>\n<p><code><br \/>\nMatchQuery mq1 = new MatchQuery(text1).field(\"topics\");<\/code><\/p>\n<p>MatchQuery mq2 = new MatchQuery(text2).field(&#8220;topics&#8221;);<\/p>\n<p>SearchQueryResult match1Result = getBucket().query(new SearchQuery(FtsConstants.FTS_IDX_CONF, mq1).fields(&#8220;title&#8221;, &#8220;attendees&#8221;, &#8220;location&#8221;, &#8220;topics&#8221;));<\/p>\n<p>log.info(&#8220;****** total \u00a0hits for match1 := &#8220;+ match1Result.hits().size());<\/p>\n<p>for (SearchQueryRow hit : match1Result.hits()) {<\/p>\n<p>JsonDocument row = bucket.get(hit.id());<\/p>\n<p>log.info(&#8220;****** scores for match 1 := &#8221; + hit.score() + &#8221; and title := &#8220;+ row.content().get(&#8220;title&#8221;) + &#8221; attendees := &#8220;+ row.content().get(&#8220;attendees&#8221;) + &#8221; topics := &#8221; + row.content().get(&#8220;topics&#8221;));<\/p>\n<p>}<\/p>\n<p>SearchQueryResult match2Result = getBucket().query(new SearchQuery(FtsConstants.FTS_IDX_CONF, mq2).fields(&#8220;title&#8221;, &#8220;attendees&#8221;, &#8220;location&#8221;, &#8220;topics&#8221;));<\/p>\n<p>log.info(&#8220;****** total \u00a0hits for match2 := &#8220;+ match2Result.hits().size());<\/p>\n<p>for (SearchQueryRow hit : match2Result.hits()) {<\/p>\n<p>JsonDocument row = bucket.get(hit.id());<\/p>\n<p>log.info(&#8220;****** scores for match 2:= &#8221; + hit.score() + &#8221; and title := &#8220;+ row.content().get(&#8220;title&#8221;) + &#8221; attendees := &#8220;+ row.content().get(&#8220;attendees&#8221;) + &#8221; topics := &#8221; + row.content().get(&#8220;topics&#8221;));<\/p>\n<p>}<\/p>\n<p>ConjunctionQuery conjunction = new ConjunctionQuery(mq1, mq2);<\/p>\n<p>SearchQueryResult result = getBucket().query(new SearchQuery(FtsConstants.FTS_IDX_CONF, conjunction).fields(&#8220;title&#8221;, &#8220;attendees&#8221;, &#8220;location&#8221;, &#8220;topics&#8221;));<\/p>\n<p>log.info(&#8220;****** total \u00a0hits for conjunction query := &#8220;+ result.hits().size());<\/p>\n<p>for (SearchQueryRow hit : result.hits()) {<\/p>\n<p>JsonDocument row = bucket.get(hit.id());<\/p>\n<p>log.info(&#8220;****** scores for conjunction query:= &#8221; + hit.score() + &#8221; and title := &#8220;+ row.content().get(&#8220;title&#8221;) + &#8221; attendees := &#8220;+ row.content().get(&#8220;attendees&#8221;) + &#8221; topics := &#8221; + row.content().get(&#8220;topics&#8221;));<\/p>\n<p>}<\/p>\n<p>DisjunctionQuery dis = new DisjunctionQuery(mq1, mq2);<\/p>\n<p>SearchQueryResult resultDis = getBucket().query(new SearchQuery(FtsConstants.FTS_IDX_CONF, dis).fields(&#8220;title&#8221;, &#8220;attendees&#8221;, &#8220;location&#8221;, &#8220;topics&#8221;));<\/p>\n<p>log.info(&#8220;****** total \u00a0hits for disjunction query := &#8220;+ resultDis.hits().size());<\/p>\n<p>for (SearchQueryRow hit : resultDis.hits()) {<\/p>\n<p>JsonDocument row = bucket.get(hit.id());<\/p>\n<p>log.info(&#8220;****** scores for disjunction query:= &#8221; + hit.score() + &#8221; and title := &#8220;+ row.content().get(&#8220;title&#8221;) + &#8221; attendees := &#8220;+ row.content().get(&#8220;attendees&#8221;) + &#8221; topics := &#8221; + row.content().get(&#8220;topics&#8221;));<\/p>\n<p>}<\/p>\n<p>BooleanQuery bool = new BooleanQuery().must(mq1).mustNot(mq2);<\/p>\n<p>SearchQueryResult resultBool = getBucket().query(new SearchQuery(FtsConstants.FTS_IDX_CONF, bool).fields(&#8220;title&#8221;, &#8220;attendees&#8221;, &#8220;location&#8221;, &#8220;topics&#8221;));<\/p>\n<p>log.info(&#8220;****** total \u00a0hits for booelan query := &#8220;+ resultBool.hits().size());<\/p>\n<p>for (SearchQueryRow hit : resultBool.hits()) {<\/p>\n<p>JsonDocument row = bucket.get(hit.id());<\/p>\n<p>log.info(&#8220;****** scores for resultBool query:= &#8221; + hit.score() + &#8221; and title := &#8220;+ row.content().get(&#8220;title&#8221;) + &#8221; attendees := &#8220;+ row.content().get(&#8220;attendees&#8221;) + &#8221; topics := &#8221; + row.content().get(&#8220;topics&#8221;));<\/p>\n<p>}<\/p>\n<p>First, individual matches are found based on the texts. We find the result set document\/s matching \u201caws\u201d as one of the topics of the conference. In the same way, we find the documents having \u201ccontainers\u201d as topics.<\/p>\n<p>Next, we start combining the individual results to form combination queries.<\/p>\n<h4>Conjunction Query<\/h4>\n<p>Conjunction query would return all matching conferences that have both \u201caws\u201d and \u201ccontainers\u201d listed as topics. Our current dataset doesn\u2019t have such a conference yet; so as expected,\u00a0when we run the query we don\u2019t get back any matching documents.<\/p>\n<p>****** total \u00a0hits for match1 := 1 \u00a0 &#8212; this matches \u201caws\u201d<\/p>\n<p>****** scores for match 1 := 0.11597946228887497 and title := ReInvent attendees := 30000 topics := [&#8220;aws&#8221;,&#8221;serverless&#8221;,&#8221;microservices&#8221;,&#8221;cloud computing&#8221;,&#8221;augmented reality&#8221;]<\/p>\n<p>****** total \u00a0hits for match2 := 1 &#8212; this matches \u201ccontainers\u201d<\/p>\n<p>****** scores for match 2:= 0.12527214351929328 and title := DockerCon attendees := 20000 topics := [&#8220;containers&#8221;,&#8221;devops&#8221;,&#8221;microservices&#8221;,&#8221;product development&#8221;,&#8221;virtualization&#8221;]<\/p>\n<p>******<strong>\u00a0total \u00a0hits for conjunction query := 0<\/strong><\/p>\n<h4>Disjunction Query<\/h4>\n<p>Disjunction query would return all matching conferences if any one of the candidate queries return a match. Since each of the individual match queries return one conference each, when we run our disjunction query, we get back both those results.<\/p>\n<p>****** <strong>total \u00a0hits for disjunction query := 2<\/strong><\/p>\n<p>****** scores for disjunction query:= 0.018374455634478874 and title := DockerCon attendees := 20000 topics := [&#8220;<strong>containers<\/strong>&#8220;,&#8221;devops&#8221;,&#8221;microservices&#8221;,&#8221;product development&#8221;,&#8221;virtualization&#8221;]<\/p>\n<p>****** scores for disjunction query:= 0.01701143945069833 and title := ReInvent attendees := 30000 topics := [&#8220;<strong>aws<\/strong>&#8220;,&#8221;serverless&#8221;,&#8221;microservices&#8221;,&#8221;cloud computing&#8221;,&#8221;augmented reality&#8221;]<\/p>\n<h4>Boolean Query<\/h4>\n<p>Using bBoolean query, we can combine different combinations of match queries. For example, BooleanQuery bool = new BooleanQuery().must(mq1).mustNot(mq2) returns all conferences that must match the first term query result which is mq1 and at the same time it must not match mq2. You can flip the combination around.<\/p>\n<p>The output of our code is as follows:<\/p>\n<p>****** <strong>total \u00a0hits for booelan query := 1<\/strong><\/p>\n<p>****** scores for resultBool query:= 0.11597946228887497 and title := ReInvent attendees := 30000 topics := [&#8220;<strong>aws<\/strong>&#8220;,&#8221;serverless&#8221;,&#8221;microservices&#8221;,&#8221;cloud computing&#8221;,&#8221;augmented reality&#8221;]<\/p>\n<p>It returns the conference that has a topic named \u201caws\u201d (which,\u00a0by the way,\u00a0is the same as mq1) and does not have a topic named \u201ccontainers\u201d (i.e.,\u00a0mq2). The only conference that satisfies both the these conditions is titled \u201cReInvent\u201d and that gets returned as output.<\/p>\n<p>I hope you found the post useful. The source\u00a0code can be found <a href=\"https:\/\/github.com\/ratchakr\/fts_demo_cb\">online<\/a>.\u00a0For a general idea about the Couchbase full-text search service, refer to the following <a href=\"https:\/\/www.couchbase.com\/blog\/couchbase-4-5-developer-preview-couchbase-fts\/\">blog post<\/a> for some useful insights:<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\uc804\uccb4 \ud14d\uc2a4\ud2b8 \uae30\ubc18 \uac80\uc0c9\uc740 \uc0ac\uc6a9\uc790\uac00 \ud14d\uc2a4\ud2b8\uc640 \ud0a4\uc6cc\ub4dc\ub97c \uae30\ubc18\uc73c\ub85c \uac80\uc0c9\ud560 \uc218 \uc788\ub294 \uae30\ub2a5\uc73c\ub85c, \uc0ac\uc6a9\uc790\uc640 \uac1c\ubc1c\uc790 \ucee4\ubba4\ub2c8\ud2f0\uc5d0\uc11c \ub9e4\uc6b0 \uc778\uae30 \uc788\ub294 \uae30\ub2a5\uc785\ub2c8\ub2e4. \ub530\ub77c\uc11c \uc804\uccb4 \ud14d\uc2a4\ud2b8 \uac80\uc0c9\uc744 \uc81c\uacf5\ud558\ub294 API\uc640 \ud504\ub808\uc784\uc6cc\ud06c\uac00 \ub9ce\ub2e4\ub294 \uac83\uc740 \ub2f9\uc5f0\ud55c \uc77c\uc774\uba70, \uadf8 \uc911 \uba87 \uac00\uc9c0 \uc608\ub85c Apache Solr, Lucene, Elasticsearch \ub4f1\uc744 \ub4e4 \uc218 \uc788\uc2b5\ub2c8\ub2e4. \ub300\ud45c\uc801\uc778 NoSQL \uc5c5\uccb4 \uc911 \ud558\ub098\uc778 Couchbase\ub294 Couchbase Server 4.5 \ub9b4\ub9ac\uc2a4\uc5d0\uc11c \uc774 \uae30\ub2a5\uc744 \ucd9c\uc2dc\ud558\uae30 \uc2dc\uc791\ud588\uc2b5\ub2c8\ub2e4. \uc774 \uae00\uc5d0\uc11c\ub294 Couchbase Java SDK\ub97c \uc0ac\uc6a9\ud558\uc5ec \uc804\uccb4 \ud14d\uc2a4\ud2b8 \uac80\uc0c9 \uc11c\ube44\uc2a4\ub97c \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc5d0 \ud1b5\ud569\ud558\ub294 \ubc29\ubc95\uc5d0 \ub300\ud574 \uc124\uba85\ud558\uaca0\uc2b5\ub2c8\ub2e4.<\/p>","protected":false},"author":53,"featured_media":13873,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[1816,2165,1818,1812],"tags":[1630],"ppma_author":[9026],"class_list":["post-2871","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-couchbase-server","category-full-text-search","category-java","category-n1ql-query","tag-spring-boot"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v27.3 (Yoast SEO v27.3) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Using Couchbase FTS in Java - The Couchbase Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.couchbase.com\/blog\/ko\/using-couchbase-full-text-search-service-java\/\" \/>\n<meta property=\"og:locale\" content=\"ko_KR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Using Couchbase Full Text Search Service in Java\" \/>\n<meta property=\"og:description\" content=\"Full-text based search is a feature that allows users to search based on texts and keywords, and is very popular among users and the developer community. So it\u2019s a no-brainer that there are lots of APIs and frameworks that offer full-text search, including Apache Solr, Lucene, and Elasticsearch, just to name a few. Couchbase, one of the leading NoSQL giants, started rolling out this feature in their Couchbase Server 4.5 release. In this post, I am going to describe how to integrate the full-text search service into their application using the Couchbase Java SDK.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.couchbase.com\/blog\/ko\/using-couchbase-full-text-search-service-java\/\" \/>\n<meta property=\"og:site_name\" content=\"The Couchbase Blog\" \/>\n<meta property=\"article:published_time\" content=\"2017-03-01T16:46:35+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-06-14T03:28:13+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2017\/02\/pasted-image-0.png\" \/>\n<meta name=\"author\" content=\"Laura Czajkowski, Developer Community Manager, Couchbase\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Laura Czajkowski, Developer Community Manager, Couchbase\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"14\ubd84\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/using-couchbase-full-text-search-service-java\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/using-couchbase-full-text-search-service-java\\\/\"},\"author\":{\"name\":\"Laura Czajkowski, Developer Community Manager, Couchbase\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#\\\/schema\\\/person\\\/5f1a0ece4e644bc8c037686fbc8f3220\"},\"headline\":\"Using Couchbase Full Text Search Service in Java\",\"datePublished\":\"2017-03-01T16:46:35+00:00\",\"dateModified\":\"2025-06-14T03:28:13+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/using-couchbase-full-text-search-service-java\\\/\"},\"wordCount\":2789,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/using-couchbase-full-text-search-service-java\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/wp-content\\\/uploads\\\/sites\\\/1\\\/2022\\\/11\\\/couchbase-nosql-dbaas.png\",\"keywords\":[\"spring-boot\"],\"articleSection\":[\"Couchbase Server\",\"Full-Text Search\",\"Java\",\"SQL++ \\\/ N1QL Query\"],\"inLanguage\":\"ko-KR\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/using-couchbase-full-text-search-service-java\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/using-couchbase-full-text-search-service-java\\\/\",\"url\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/using-couchbase-full-text-search-service-java\\\/\",\"name\":\"Using Couchbase FTS in Java - The Couchbase Blog\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/using-couchbase-full-text-search-service-java\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/using-couchbase-full-text-search-service-java\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/wp-content\\\/uploads\\\/sites\\\/1\\\/2022\\\/11\\\/couchbase-nosql-dbaas.png\",\"datePublished\":\"2017-03-01T16:46:35+00:00\",\"dateModified\":\"2025-06-14T03:28:13+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/using-couchbase-full-text-search-service-java\\\/#breadcrumb\"},\"inLanguage\":\"ko-KR\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/using-couchbase-full-text-search-service-java\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"ko-KR\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/using-couchbase-full-text-search-service-java\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/wp-content\\\/uploads\\\/sites\\\/1\\\/2022\\\/11\\\/couchbase-nosql-dbaas.png\",\"contentUrl\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/wp-content\\\/uploads\\\/sites\\\/1\\\/2022\\\/11\\\/couchbase-nosql-dbaas.png\",\"width\":1800,\"height\":630},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/using-couchbase-full-text-search-service-java\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Using Couchbase Full Text Search Service in Java\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/\",\"name\":\"The Couchbase Blog\",\"description\":\"Couchbase, the NoSQL Database\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"ko-KR\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#organization\",\"name\":\"The Couchbase Blog\",\"url\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"ko-KR\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/wp-content\\\/uploads\\\/2023\\\/04\\\/admin-logo.png\",\"contentUrl\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/wp-content\\\/uploads\\\/2023\\\/04\\\/admin-logo.png\",\"width\":218,\"height\":34,\"caption\":\"The Couchbase Blog\"},\"image\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#\\\/schema\\\/logo\\\/image\\\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#\\\/schema\\\/person\\\/5f1a0ece4e644bc8c037686fbc8f3220\",\"name\":\"Laura Czajkowski, Developer Community Manager, Couchbase\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"ko-KR\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/bc8eebaf25cbe39bc12fd7b1ef92550becc3953ab877a3f0285a59ec2d30b754?s=96&d=mm&r=g9deb07d5daaa00220534c31768bc4409\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/bc8eebaf25cbe39bc12fd7b1ef92550becc3953ab877a3f0285a59ec2d30b754?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/bc8eebaf25cbe39bc12fd7b1ef92550becc3953ab877a3f0285a59ec2d30b754?s=96&d=mm&r=g\",\"caption\":\"Laura Czajkowski, Developer Community Manager, Couchbase\"},\"description\":\"Laura Czajkowski is the Snr. Developer Community Manager at Couchbase overseeing the community. She\u2019s responsible for our monthly developer newsletter.\",\"url\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/ko\\\/author\\\/laura-czajkowski\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Using Couchbase FTS in Java - The Couchbase Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.couchbase.com\/blog\/ko\/using-couchbase-full-text-search-service-java\/","og_locale":"ko_KR","og_type":"article","og_title":"Using Couchbase Full Text Search Service in Java","og_description":"Full-text based search is a feature that allows users to search based on texts and keywords, and is very popular among users and the developer community. So it\u2019s a no-brainer that there are lots of APIs and frameworks that offer full-text search, including Apache Solr, Lucene, and Elasticsearch, just to name a few. Couchbase, one of the leading NoSQL giants, started rolling out this feature in their Couchbase Server 4.5 release. In this post, I am going to describe how to integrate the full-text search service into their application using the Couchbase Java SDK.","og_url":"https:\/\/www.couchbase.com\/blog\/ko\/using-couchbase-full-text-search-service-java\/","og_site_name":"The Couchbase Blog","article_published_time":"2017-03-01T16:46:35+00:00","article_modified_time":"2025-06-14T03:28:13+00:00","og_image":[{"url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2017\/02\/pasted-image-0.png","type":"","width":"","height":""}],"author":"Laura Czajkowski, Developer Community Manager, Couchbase","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Laura Czajkowski, Developer Community Manager, Couchbase","Est. reading time":"14\ubd84"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.couchbase.com\/blog\/using-couchbase-full-text-search-service-java\/#article","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/using-couchbase-full-text-search-service-java\/"},"author":{"name":"Laura Czajkowski, Developer Community Manager, Couchbase","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/5f1a0ece4e644bc8c037686fbc8f3220"},"headline":"Using Couchbase Full Text Search Service in Java","datePublished":"2017-03-01T16:46:35+00:00","dateModified":"2025-06-14T03:28:13+00:00","mainEntityOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/using-couchbase-full-text-search-service-java\/"},"wordCount":2789,"commentCount":0,"publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/using-couchbase-full-text-search-service-java\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","keywords":["spring-boot"],"articleSection":["Couchbase Server","Full-Text Search","Java","SQL++ \/ N1QL Query"],"inLanguage":"ko-KR","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.couchbase.com\/blog\/using-couchbase-full-text-search-service-java\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.couchbase.com\/blog\/using-couchbase-full-text-search-service-java\/","url":"https:\/\/www.couchbase.com\/blog\/using-couchbase-full-text-search-service-java\/","name":"Using Couchbase FTS in Java - The Couchbase Blog","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/using-couchbase-full-text-search-service-java\/#primaryimage"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/using-couchbase-full-text-search-service-java\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","datePublished":"2017-03-01T16:46:35+00:00","dateModified":"2025-06-14T03:28:13+00:00","breadcrumb":{"@id":"https:\/\/www.couchbase.com\/blog\/using-couchbase-full-text-search-service-java\/#breadcrumb"},"inLanguage":"ko-KR","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.couchbase.com\/blog\/using-couchbase-full-text-search-service-java\/"]}]},{"@type":"ImageObject","inLanguage":"ko-KR","@id":"https:\/\/www.couchbase.com\/blog\/using-couchbase-full-text-search-service-java\/#primaryimage","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","width":1800,"height":630},{"@type":"BreadcrumbList","@id":"https:\/\/www.couchbase.com\/blog\/using-couchbase-full-text-search-service-java\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.couchbase.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Using Couchbase Full Text Search Service in Java"}]},{"@type":"WebSite","@id":"https:\/\/www.couchbase.com\/blog\/#website","url":"https:\/\/www.couchbase.com\/blog\/","name":"\uce74\uc6b0\uce58\ubca0\uc774\uc2a4 \ube14\ub85c\uadf8","description":"NoSQL \ub370\uc774\ud130\ubca0\uc774\uc2a4, Couchbase","publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"ko-KR"},{"@type":"Organization","@id":"https:\/\/www.couchbase.com\/blog\/#organization","name":"\uce74\uc6b0\uce58\ubca0\uc774\uc2a4 \ube14\ub85c\uadf8","url":"https:\/\/www.couchbase.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"ko-KR","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","width":218,"height":34,"caption":"The Couchbase Blog"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/5f1a0ece4e644bc8c037686fbc8f3220","name":"Laura Czajkowski, \uac1c\ubc1c\uc790 \ucee4\ubba4\ub2c8\ud2f0 \uad00\ub9ac\uc790, Couchbase","image":{"@type":"ImageObject","inLanguage":"ko-KR","@id":"https:\/\/secure.gravatar.com\/avatar\/bc8eebaf25cbe39bc12fd7b1ef92550becc3953ab877a3f0285a59ec2d30b754?s=96&d=mm&r=g9deb07d5daaa00220534c31768bc4409","url":"https:\/\/secure.gravatar.com\/avatar\/bc8eebaf25cbe39bc12fd7b1ef92550becc3953ab877a3f0285a59ec2d30b754?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/bc8eebaf25cbe39bc12fd7b1ef92550becc3953ab877a3f0285a59ec2d30b754?s=96&d=mm&r=g","caption":"Laura Czajkowski, Developer Community Manager, Couchbase"},"description":"\ub85c\ub77c \ucc60\ucf54\ube0c\uc2a4\ud0a4\ub294 \uce74\uc6b0\uce58\ubca0\uc774\uc2a4\uc758 Snr. \uac1c\ubc1c\uc790 \ucee4\ubba4\ub2c8\ud2f0 \ub9e4\ub2c8\uc800\ub85c \uce74\uc6b0\uce58\ubca0\uc774\uc2a4\uc758 \ucee4\ubba4\ub2c8\ud2f0\ub97c \ucd1d\uad04\ud558\uace0 \uc788\uc2b5\ub2c8\ub2e4. \uadf8\ub140\ub294 \uc6d4\uac04 \uac1c\ubc1c\uc790 \ub274\uc2a4\ub808\ud130\ub97c \ub2f4\ub2f9\ud558\uace0 \uc788\uc2b5\ub2c8\ub2e4.","url":"https:\/\/www.couchbase.com\/blog\/ko\/author\/laura-czajkowski\/"}]}},"acf":[],"authors":[{"term_id":9026,"user_id":53,"is_guest":0,"slug":"laura-czajkowski","display_name":"Laura Czajkowski, Developer Community Manager, Couchbase","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/bc8eebaf25cbe39bc12fd7b1ef92550becc3953ab877a3f0285a59ec2d30b754?s=96&d=mm&r=g","0":null,"1":"","2":"","3":"","4":"","5":"","6":"","7":"","8":""}],"_links":{"self":[{"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/posts\/2871","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/users\/53"}],"replies":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/comments?post=2871"}],"version-history":[{"count":0,"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/posts\/2871\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/media\/13873"}],"wp:attachment":[{"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/media?parent=2871"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/categories?post=2871"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/tags?post=2871"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/ppma_author?post=2871"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}