JSON parsing errors when using Mustache Conditional


(David Baughman) #1

Hey everyone. I'm new to Elasticsearch, and am trying to figure out how to use Search Templates. They seem like a very promising way to simplify client-size search requests. But when I try to upload a template that uses a Mustache section (e.g. {{#propName}}), it is obviously not valid JSON and the request fails.

So my question is, how am I supposed to upload a Mustache template? BTW, I'm using Elasticsearch on AWS, so storing a .mustache file isn't an option.

Thanks!

Request

curl -X PUT "https://hostname/_template/product_categories" -H 'Content-Type: application/json' -d'
{
  "template": {
    "from": 0,
    "size": 30,
    "stored_fields": [],
    "_source": [ "category.name" ],
    "query": {
      "function_score": {
        "functions": [
          {
            "field_value_factor": {
              "field": "popularity",
              "factor": 1.004,
              "missing": 0
            }
          },
          {
            "filter": { "match": { "is_accessory": true }},
            "weight": 0.48
          }
        ],
        "query": {
          "bool": {
            "must": {
              {{#searchTerm}}
              "multi_match": {
                "query": "{{ searchTerm }}",
                "fuzziness": "auto",
                "operator": "and",
                "type": "best_fields",
                "fields": [
                  "name.regular.{{ lang }}^2",
                  "description.short.{{ lang }}",
                  "keywords.{{ lang }}^0.5",
                  "description.long.{{ lang }}^0.25"
                ]
              }
              {{/searchTerm}}
              {{#points}}
              "term": {
                "points": {{ points }}
              }
              {{/points}}
            },
            "filter": {
              "bool": {
                "must": [
                  { "term": { "channel_id": 1 }},
                  { "term": { "doc_type": "product" }}
                ]
              }
            }
          }
        }
      }
    }
  }
}
'

Response

{
  "error": {
    "root_cause": [{
      "type": "parse_exception",
      "reason": "Failed to parse content to map"
    }],
    "type": "parse_exception",
    "reason": "Failed to parse content to map",
    "caused_by": {
      "type": "json_parse_exception",
      "reason": "Unexpected character ('{' (code 123)): was expecting double-quote to start field name\n at [Source: org.elasticsearch.common.bytes.BytesReference$MarkSupportingStreamInputWrapper@1eff8d7e; line: 26, column: 16]"
    }
  },
  "status": 400
}

(Abdon Pijpelink) #2

Welcome to the Elastic community! There's a couple of things wrong with your request.

First, you're trying to register the search template using the /_template endpoint, but that endpoint is for index templates (a way of preconfiguring settings and mappings for new indexes). Search templates need to be registered as mustache scripts using the _scripts endpoint.

Second, if you use conditionals, the request is not valid JSON, as you already noticed. In that case, you need to register the template source as a string.

So, a valid request would look something like this:

curl -XPOST "http://hostname:9200/_scripts/product_categories" -H 'Content-Type: application/json' -d'
{
  "script": {
    "lang": "mustache",
    "source":" {    \"from\": 0,    \"size\": 30,    \"stored_fields\": [],    \"_source\": [ \"category.name\" ],    \"query\": {      \"function_score\": {        \"functions\": [          {            \"field_value_factor\": {              \"field\": \"popularity\",              \"factor\": 1.004,              \"missing\": 0            }          },          {            \"filter\": { \"match\": { \"is_accessory\": true }},            \"weight\": 0.48          }        ],        \"query\": {          \"bool\": {            \"must\": {              {{#searchTerm}}              \"multi_match\": {                \"query\": \"{{ searchTerm }}\",                \"fuzziness\": \"auto\",                \"operator\": \"and\",                \"type\": \"best_fields\",                \"fields\": [                  \"name.regular.{{ lang }}^2\",                  \"description.short.{{ lang }}\",                  \"keywords.{{ lang }}^0.5\",                  \"description.long.{{ lang }}^0.25\"                ]              }              {{/searchTerm}}              {{#points}}              \"term\": {                \"points\": {{ points }}              }              {{/points}}            },            \"filter\": {              \"bool\": {                \"must\": [                  { \"term\": { \"channel_id\": 1 }},                  { \"term\": { \"doc_type\": \"product\" }}                ]              }            }          }        }      }    }}"
  }
}'

(system) #3

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.