How to use Phrase Search in Elasticsearch 6 using NodeJS

Introduction

It’s true that you can quickly locate an exact phrase in an index in Elasticsearch. To accomplish the task, you’ll want to use Phrase Search. But if you’re just starting phrase search in Elasticsearch, you may be tempted to conduct a multiple word search with the match query.

Here’s why match works for single-word queries but not phrase queries. With match, when you enter a phrase that contains two or more words, the results will also include data with only one of those words. Let’s explain further. Say you use the match query to find the phrase “Strawberry Cake.” You just want the results that contain an exact match for “Strawberry Cake.” The match query will return those results, but also in the mix you could get “Strawberry Ice Cream,” and “Chocolate Cake,” because the former has the word “Strawberry” and the latter has the word “Cake”.

This tutorial shows you step-by-step how to use Phrase Search. If you’re already familiar with the method and would like to skip right to the code, click here to go to Just the Code.

Prerequisites

Before we show you how to perform fuzzy query matches with Elasticsearch in Javascript, it’s important to make sure a few prerequisites are in place. There are only a few of system requirements for this task: NodeJS needs to be installed The elasticsearch npm module installed. A simple npm install elasticsearch should work in most cases. Elasticsearch also needs to be installed and running. * In our example, we have Elasticsearch installed locally using the default port of 9200. If your Elasticsearch installation is running on a different server, you’ll need to modify your javascript syntax accordingly.

An Example Using the Phrase Search Query

Let’s look at an example that uses an index called store, which represents a small grocery store. This store index contains a type called products which lists the store’s products. To keep things simple, our example dataset will only contain a handful of products with just the following fields: id, price, quantity, and department. The code below shows the JSON used to create the dataset:

idnamepricequantitydepartment
1Multi-Grain Cereal4.994Packaged Foods
21lb Ground Beef3.9929Meat and Seafood
3Dozen Apples2.4912Produce
4Chocolate Bar1.292Packaged Foods, Checkout
51 Gallon Milk3.2916Dairy
60.5lb Jumbo Shrimp5.2912Meat and Seafood
7Wheat Bread1.295Bakery
8Pepperoni Pizza2.995Frozen
912 Pack Cola5.296Packaged Foods
10Lime Juice0.9920Produce
1112 Pack Cherry Cola5.595Packaged Foods
121 Gallon Soy Milk3.3910Dairy
131 Gallon Vanilla Soy Milk3.499Dairy
141 Gallon Orange Juice3.294Juice

Here is the json we used to define the mapping if our index:

{
    "mappings": {
        "products": {
            "properties" : {
                "name": { "type": "text"},
                "price": { "type": "double"},
                "quantity": { "type": "integer"},
                "department": { "type": "keyword"}
            }
        }
    }
}

Conduct the Phrase Search Query

Your query for a general match to the two-word phrase “Cherry Cola” would look similar to this:

File: app.js

var elasticsearch = require("elasticsearch");

var client = new elasticsearch.Client({
  hosts: ["http://localhost:9200"]
});

/* Match Search */
client.search({
  index: 'store',
  type: 'products',
  body: {
    "query": {  
      "match": {
        "name": "Cherry Cola"
      }
    }
  }
}).then(function(resp) {
  console.log("Successful query!");
  console.log(JSON.stringify(resp, null, 4));
}, function(err) {
  console.trace(err.message);``
});

Run app.js in the terminal like this:

$ node app.js

Response:

Successful query!
{
    "took": 29,
    "timed_out": false,
    "_shards": {
        "total": 5,
        "successful": 5,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": 2,
        "max_score": 1.3469357,
        "hits": [
            {
                "_index": "store",
                "_type": "products",
                "_id": "9",
                "_score": 1.3469357,
                "_source": {
                    "id": "9",
                    "name": "12 Pack Cola",
                    "price": 5.29,
                    "quantity": 6,
                    "department": [
                        "Packaged Foods"
                    ]
                }
            },
            {
                "_index": "store",
                "_type": "products",
                "_id": "11",
                "_score": 1.219939,
                "_source": {
                    "id": "11",
                    "name": "12 Pack Cherry Cola",
                    "price": 5.59,
                    "quantity": 5,
                    "department": [
                        "Packaged Foods"
                    ]
                }
            }
        ]
    }
}

With the match query, our results contains two results it: “12 Pack Cola” and “12 Pack Cherry Cola”.

If you’re looking for an exact match to the phrase “Cherry Cola”, use Phrase Search. This way you’ll receive more precision in your search results. Simply change the match query to match_phrase.

var elasticsearch = require("elasticsearch");

var client = new elasticsearch.Client({
  hosts: ["http://localhost:9200"]
});

/* Match Phrase Search */
client.search({
  index: 'store',
  type: 'products',
  body: {
    "query": {  
      "match_phrase": {
        "name": "Cherry Cola"
      }
    }
  }
}).then(function(resp) {
  console.log("Successful query!");
  console.log(JSON.stringify(resp, null, 4));
}, function(err) {
  console.trace(err.message);``
});

Response: `js $ node app.js Successful query! {


"took": 1184,
"timed_out": false,
"_shards": {
    "total": 5,
    "successful": 5,
    "skipped": 0,
    "failed": 0
},
"hits": {
    "total": 1,
    "max_score": 1.219939,
    "hits": [
        {
            "_index": "store",
            "_type": "products",
            "_id": "11",
            "_score": 1.219939,
            "_source": {
                "id": "11",
                "name": "12 Pack Cherry Cola",
                "price": 5.59,
                "quantity": 5,
                "department": [
                    "Packaged Foods"
                ]
            }
        }
    ]
}

} `

As you can see, the match_phrase query limits your query to a result set with exact matches to that phrase.

Conclusion

This Phrase Search in Elasticsearch 6 tutorial showed you how to save time by using the query match_phrase as opposed to match. This is because the Phrase Search match_phrase query zeros in on exactly the search terms you query.

By the way, phrase searching using the match_phrase query isn’t the only way to search efficiently in Elasticsearch 6. The slop parameter may be of interest to you as well. Read more on it here. Meanwhile, to learn more about match_phrase look at the Elasticsearch documentation or reach out to us. We’re here to help.

Just the Code

Here’s a code example showing Phrase Search, the match_phrase query in action.

var elasticsearch = require("elasticsearch");

var client = new elasticsearch.Client({
  hosts: ["http://localhost:9200"]
});

/* Match Phrase Search */
client.search({
  index: 'store',
  type: 'products',
  body: {
    "query": {  
      "match_phrase": {
        "name": "Cherry Cola"
      }
    }
  }
}).then(function(resp) {
  console.log("Successful query!");
  console.log(JSON.stringify(resp, null, 4));
}, function(err) {
  console.trace(err.message);``
});

Pilot the ObjectRocket Platform Free!

Try Fully-Managed CockroachDB, Elasticsearch, MongoDB, PostgreSQL (Beta) or Redis.

Get Started

Keep in the know!

Subscribe to our emails and we’ll let you know what’s going on at ObjectRocket. We hate spam and make it easy to unsubscribe.