NewBee
NewBee

Reputation: 53

Fielddata is disabled on text fields by default even after enabling it

I have setup ElasticSearch 5.6 with below details
Index - productcatalog
Type - product
I have multiple product record in ElasticSearch, below is one of that

                    "id": "xprod2148",
                    "name": "Acadia Wood Chair",
                    "type": null,
                    "description": "Craftsman meets classic in this attractive wood chair",
                    "items": [
                        {
                            "id": "xsku2148",
                            "type": "0",
                            "name": "Acadia Wood Chair",
                            "prices": [
                                {
                                    "type": "listPrices",
                                    "value": "179"
                                },
                                {
                                    "type": "plist3080002",
                                    "value": "121.49"
                                }
                            ],
                            "inventories": [
                                {
                                    "availabilityStatus": "In Stock",
                                    "url": "https://mesh.inventory.com/item?id=xsku2148"
                                }
                            ]
                        }
                    ],
                    "category": {
                        "id": "homeStoreSeatingDining",
                        "name": "Dining Chairs",
                        "href": null,
                        "parent": null
                    },
                    "images": [
                        {
                            "id": "m2966",
                            "name": "/crsdocroot/content/images/products/small/ST_AcadiaWoodChair_small.jpg",
                            "url": "Images/Product/crsdocroot/content/images/products/small/ST_AcadiaWoodChair_small.jpg"
                        },
                        {
                            "id": "m2968",
                            "name": "/crsdocroot/content/images/products/thumb/ST_AcadiaWoodChair_thumb.jpg",
                            "url": "Images/Product/crsdocroot/content/images/products/thumb/ST_AcadiaWoodChair_thumb.jpg"
                        },
                        {
                            "id": "m2969",
                            "name": "/crsdocroot/content/images/products/large/ST_AcadiaWoodChair_large.jpg",
                            "url": "Images/Product/crsdocroot/content/images/products/large/ST_AcadiaWoodChair_large.jpg"
                        }
                    ],
                    "brand": "Style by Zhanna"
                }
            }

In addition of this I am building a REST API using the RestHighLevelClient to query elastic Search.
What I am trying to achieve?
Building a REST api, to query products by id,name,description,brand and allows sorting and filtering.
What I have done till now ?
I have implemented the basic search and now want to do the sorting based on fields like id,name and brand.

Following class is responsible for fetching data from ElasticSearch and contains code for sort feature(not working right now)

package com.mesh.productlisting.dao.elasticsearch.impl;

import org.apache.http.Header;
import org.apache.http.message.BasicHeader;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Conditional;
import org.springframework.stereotype.Component;

import com.mesh.constants.CommonConstants;
import com.mesh.exception.DataAccessException;
import com.mesh.exception.util.ErrorResolver;
import com.mesh.productlisting.config.ElasticSearchRestClient;
import com.mesh.productlisting.config.condition.EnableElasticSearchCondition;
import com.mesh.productlisting.constants.SearchConstants;
import com.mesh.productlisting.dao.ProductDAO;

@Component
@Conditional(EnableElasticSearchCondition.class)
public class ElasticSearchProductDAOImpl implements ProductDAO {

    private final String className = ElasticSearchProductDAOImpl.class.getName();

    private final Logger logger = LoggerFactory.getLogger(ElasticSearchProductDAOImpl.class);

    @Value("${elasticsearch.productIndex}")
    private String productIndex;

    @Value("${elasticsearch.productIndexType}")
    private String productIndexType;

    @Value("${elasticsearch.product.searchfields}")
    private String searchProductByFields;

    @Autowired
    private ElasticSearchRestClient elasticSearchRestClient;

    @Autowired
    private ErrorResolver errorResolver;

    /**
     * This method returns the ElasticSearch response
     */
    @Override
    public String fetchProducts(String query, String rows, String filterQuery, String sortByField, String sortOrder,
            String start, String priceStart, String priceEnd) {

        final String methodName = "fetchProducts";
        logger.info("Entering " + className + " " + methodName);
        String jsonResponse = null;

        jsonResponse = queryElasticSearch(query, rows, filterQuery, sortByField, sortOrder, start, priceStart,
                priceEnd);

        logger.info("Exiting " + className + " " + methodName);
        return jsonResponse;
    }

    /**
     * This method query the ElasticSearch and gets the response
     * 
     * @param query
     * @param rows
     * @param filterQuery
     * @param sortByField
     * @param sortOrder
     * @param start
     * @param priceStart
     * @param priceEnd
     * @return String
     */
    private String queryElasticSearch(String query, String rows, String filterQuery, String sortByField,
            String sortOrder, String start, String priceStart, String priceEnd) {

        RestHighLevelClient restHighLevelClient = elasticSearchRestClient.getHighLevelRestClient();

        SearchRequest searchRequest = new SearchRequest(productIndex);
        searchRequest.types(productIndexType);
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

        if (start != null) {
            searchSourceBuilder.from(Integer.parseInt(start));
        }
        if (rows != null) {
            searchSourceBuilder.size(Integer.parseInt(rows));
        }

        String searchProductByFieldsArray[] = searchProductByFields.split(",");

        searchSourceBuilder.query(QueryBuilders.multiMatchQuery(query, searchProductByFieldsArray));

        searchSourceBuilder.sort(new FieldSortBuilder("brand").order(SortOrder.DESC));

        //searchSourceBuilder.fetchSource(false);

        searchRequest.source(searchSourceBuilder);

        Header headers = new BasicHeader("Content-Type", "application/json");

        SearchResponse searchResponse = null;

        try {

            searchResponse = restHighLevelClient.search(searchRequest, headers);

        } catch (Exception e) {

            e.printStackTrace();

            logger.error("exception caught while querying ElasticSearch " + e.getMessage());

            throw new DataAccessException(CommonConstants.SERVICE_NOT_AVAILABLE, errorResolver
                    .getErrorMessage(SearchConstants.ElASTIC_SEARCH_UNAVAILABLE, CommonConstants.EMPTY_STRING));

        }

        if (searchResponse == null)
            throw new DataAccessException(CommonConstants.BAD_REQUEST,
                    errorResolver.getErrorMessage(SearchConstants.NO_PRODUCT_FOUND, CommonConstants.EMPTY_STRING));
        else {

            return searchResponse.toString();
        }
    }

}


Currently I am trying to do sort on brand and I am getting exception as below

{"error":{"root_cause":[{"type":"illegal_argument_exception","reason":"Fielddata is disabled on text fields by default. Set fielddata=true on [brand] in order to load fielddata in memory by uninverting the inverted index. Note that this can however use significant memory. Alternatively use a keyword field instead."}],"type":"search_phase_execution_exception","reason":"all shards failed","phase":"query","grouped":true,"failed_shards":[{"shard":0,"index":"productcatalog","node":"L_QzCcz-Q6-T5Up3Om248A","reason":{"type":"illegal_argument_exception","reason":"Fielddata is disabled on text fields by default. Set fielddata=true on [brand] in order to load fielddata in memory by uninverting the inverted index. Note that this can however use significant memory. Alternatively use a keyword field instead."}}]},"status":400}

To rectify this I have followed this https://www.elastic.co/guide/en/elasticsearch/reference/master/fielddata.html

and tried in POSTMAN (snapshot attached)

check image link for postman request and response


Even after following the ElasticSearch Docs , I am unable to solve this issue and keep getting the same error message except for _uid field.

Thanks in Advance

Upvotes: 3

Views: 2224

Answers (1)

Narendra Jaggi
Narendra Jaggi

Reputation: 1338

In the postman,URL is wrong, try to hit by using the below one
http://localhost:9200/productcatalog/_mapping/product
_mapping is missing as of now.
Same is mentioned in the URL you have given https://www.elastic.co/guide/en/elasticsearch/reference/master/fielddata.html

You should get response like below
Response

Upvotes: 2

Related Questions