I want to add one field to the document which should be searchable but when we do get/search it should not appear under _source.

I have tried index and store options but its not achievable through it.
Its more like _all or copy_to, but in my case value is provided by me (not collecting from other fields of the document.)

I am looking for mapping through which I can achieve below cases.

When I put document :

PUT my_index/_doc/1
{
  "title":   "Some short title",
  "date":    "2015-01-01",
  "content": "A very long content field..."
}

and do search

GET my_index/_search

output should be

{
    "hits" : {
    "total" : 1,
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "my_index",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.0,
        "_source" : {
          "title" : "Some short title",
          "date" : "2015-01-01"
        }
      }
    ]
  }
}

also when I do the below search

GET my_index/_search
{
  "query": {
    "query_string": {
      "default_field": "content",
      "query": "long content"
    }
  }
}

it should result me

"hits" : {
    "total" : 1,
    "max_score" : 0.5753642,
    "hits" : [
      {
        "_index" : "my_index",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 0.5753642,
        "_source" : {
          "title" : "Some short title",
          "date" : "2015-01-01"
        }
      }
    ]
  }

1

Simply use source filtering to exclude the content field:

GET my_index/_search
{
  "_source": {
    "excludes": [ "content" ]
  },
  "query": {
    "query_string": {
      "default_field": "content",
      "query": "long content"
    }
  }
}

5

We can achieve this using below mapping :

PUT my_index
{
  "mappings": {

    "_doc": {
      "_source": {
        "excludes": [
          "content"
        ]
      },
      "properties": {
        "title": {
          "type": "text",
          "store": true 
        },
        "date": {
          "type": "date",
          "store": true 
        },
        "content": {
          "type": "text"
        }
      }
    }
  }
}

Add document :

PUT my_index/_doc/1
{
  "title":   "Some short title",
  "date":    "2015-01-01",
  "content": "A very long content field..."
}

When you run the query to search content on the field ‘content’ :

GET my_index/_search
{
  "query": {
    "query_string": {
      "default_field": "content",
      "query": "long content"
    }
  }
}

You will get the result with hits as below:

"hits" : {
    "total" : 1,
    "max_score" : 0.5753642,
    "hits" : [
      {
        "_index" : "my_index",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 0.5753642,
        "_source" : {
          "date" : "2015-01-01",
          "title" : "Some short title"
        }
      }
    ]
  }

It hides the field ‘content’. 🙂

Hence achieved it with the help of mapping. You don’t need to exclude it from query each time you make get/search call.

More read on source :
https://www.elastic.co/guide/en/elasticsearch/reference/6.6/mapping-source-field.html

1