Add Autocomplete to Your Application
- how-to
Use autocomplete to add suggestions for a user’s Search query as they type in your application.
After you create and configure a Search index that supports autocomplete, configure your application to return results from the Search Service.
Prerequisites
-
You’ve deployed the Search Service on a node in your database.
-
You have a bucket with scopes and collections in your database.
-
Your user account has the Search Admin role for the bucket where you want to create the index.
-
You’ve created a compatible Search index. For more information, see Configure an Autocomplete Search Index.
Procedure
To add autocomplete with the Serach Service to your application:
-
To test that your Search index was configured correctly, do one of the following:
-
Run a Search query from the REST API with 2-8 characters in the
query
property. -
Run a Search query from the Web Console with 2-8 characters in the Search field.
For example, with the
travel-sample
bucket, you could enter the stringsBe
,Bea
,Beau
, andBeauf
to find a document with the textBeaufort Hotel
. -
-
Configure your application to return results from the Search Service.
The following examples simulate a user typing an input string and return search results for each partial string:
-
C#
-
Go
-
Java
-
JavaScript
-
Python
using Couchbase; using Couchbase.Search.Queries.Simple; await using var cluster = await Cluster.ConnectAsync(new ClusterOptions { ConnectionString = "CB_HOSTNAME", UserName = "CB_USERNAME", Password = "CB_PASSWORD", Buckets = new List<string>{"travel-sample"} }.ApplyProfile("wan-development")); var searchString = "Beaufort Hotel"; for (var i = 2; i <= 8; i++) { var lettersEntered = searchString.Substring(0, i); Console.WriteLine($"Input <{lettersEntered}>, len: {lettersEntered.Length}"); await FtsMatchPrefix(lettersEntered); } async Task FtsMatchPrefix(string letters) { try { var results = await cluster.SearchQueryAsync("e-ngram-2-8", new QueryStringQuery(letters), options => { options.Limit(8); options.Fields("name"); }); results.Hits.ToList().ForEach(row => { Console.WriteLine($"{row.Id}, {row.Fields}"); }); Console.WriteLine(results); } catch (Exception e) { Console.WriteLine(e); } }
package main import ( "os" "fmt" "math" "log" "github.com/couchbase/gocb/v2" "github.com/couchbase/gocb/v2/search" ) func main() { cluster, err := gocb.Connect( os.Getenv("CB_HOSTNAME"), gocb.ClusterOptions{ Authenticator: gocb.PasswordAuthenticator{ Username: os.Getenv("CB_USERNAME"), Password: os.Getenv("CB_PASSWORD"), }, }) if err != nil { log.Fatal(err) } iterStr := "Beaufort Hotel" maxsz := int(math.Min(float64(len(iterStr)), float64(8))) for i := 2; i <= maxsz; i++ { testStr := iterStr[0:i] fmt.Printf("Input <%s>, len: %d\n", testStr, len(testStr)); results, err := cluster.SearchQuery( "e-ngram-2-8", search.NewQueryStringQuery(testStr), &gocb.SearchOptions { Fields: []string{"name"}, Limit: 8, }, ) if err != nil { log.Fatal(err) } for results.Next() { row := results.Row() docID := row.ID var fields interface {} err := row.Fields( & fields) if err != nil { panic(err) } fmt.Printf("Document ID: %s, fields: %v\n", docID, fields) } err = results.Err() if err != nil { log.Fatal(err) } } }
import com.couchbase.client.java.Cluster; import com.couchbase.client.java.json.JsonObject; import com.couchbase.client.java.search.SearchOptions; import com.couchbase.client.java.search.SearchQuery; import com.couchbase.client.java.search.result.SearchResult; import com.couchbase.client.java.search.result.SearchRow; public class MockTypeAheadEnGram { static String connstrn = System.getenv("CB_HOSTNAME"); static String username = System.getenv("CB_USERNAME"); static String password = System.getenv("CB_PASSWORD"); public static void main(String... args) { Cluster cluster = Cluster.connect(connstrn, username, password); String iterStr = "Beaufort Hotel"; for (int i=2; i<=Math.min(8, iterStr.length());i++) { String testStr = iterStr.substring(0, i); System.out.println("Input <" + testStr + ">, len: " + testStr.length()); SearchQuery query = SearchQuery.queryString(testStr); SearchOptions options = SearchOptions.searchOptions().limit(8).skip(0).explain(false).fields("name"); SearchResult result = cluster.searchQuery("e-ngram-2-8" , query, options); for (SearchRow row : result.rows()) { System.out.println(row.id() + "," + row.fieldsAs(JsonObject.class) ); } } } }
const couchbase = require('couchbase') const main = async () => { const hostname = process.env.CB_HOSTNAME const username = process.env.CB_USERNAME const password = process.env.CB_PASSWORD const bucketName = 'travel-sample' const cluster = await couchbase.connect(hostname, {username: username, password: password }) const ftsMatchPrefix = async (term) => { try { const result = await cluster.searchQuery( "e-ngram-2-8", couchbase.SearchQuery.queryString(term), { limit: 8, fields: ["name"] } ) result.rows.forEach((row) => { console.log(row.id,row.fields)}) } catch (error) { console.error(error) } } const inputStr = "Beaufort Hotel" for (let i = 2; i <= 8; i++) { var testStr = inputStr.substring(0, i); console.log("Input <" + testStr + ">, len: " + testStr.length) const res = await ftsMatchPrefix(testStr) } } main()
from couchbase.cluster import Cluster, ClusterOptions from couchbase.auth import PasswordAuthenticator from couchbase.exceptions import CouchbaseException import couchbase.search as search import os username = os.getenv("CB_USERNAME", default=None) password = os.getenv("CB_PASSWORD", default=None) hostname = os.getenv("CB_HOSTNAME", default=None) cluster = Cluster.connect( "couchbase://" + hostname, ClusterOptions(PasswordAuthenticator(username,password))) try: inputStr = "Beaufort Hotel" for i in range(2, min(8,len(inputStr))): testStr = inputStr[0:i] print("Input <" + testStr + ">, len: " + str(len(testStr))); result = cluster.search_query( "e-ngram-2-8", search.QueryStringQuery(testStr), search.SearchOptions(limit=8, fields=["name"])) for row in result.rows(): print(row.id,row.fields) except CouchbaseException as ex: import traceback traceback.print_exc()
-
Next Steps
After you add autocomplete to your application, to improve your search results, you can:
-
Change the JSON payload for your Search index.