Unable to enforce parent-child relationship while creating indexes thru Java API based Code


(Amal Saha) #1

Hello Dear,

I had the following code that worked fine with Elasticsearch v0.90.0. This code created child index for a given parent index. When I upgraded ES to 2.x, I get the error, at runtime (there is no compilation error),
java.lang.IllegalArgumentException: Can't specify parent if no parent field has been configured

The line that creates the hell is indicated with comment. It is related to the call " indexRequestbuilder.setParent(parentId)". Please note that I am using Java API.

I would highly appreciate suggestion from the community, for resolving this issue.

Thanks and Regards,
Amal

------------------------------------------------------- code snippet ---------------------------------------------

public void createChildIndex(final Entity entity, final Tenant tenant) throws SearchEngineException {  
   try {
        Map<String, Object> source = entityIndexDocumentPurveyor.purveyDocument(entity, tenant);
        String parentId = String.valueOf(tenant.getId()); 
        String indexName = "entities";    
        String indexId = String.valueOf(entity.getId());   
        XContentBuilder builder = XContentFactory.jsonBuilder();   
        if (source.keySet().size() > 0) { 
            String indexType = StringUtils.substringAfterLast(entity.getClass().getName(), ".").toLowerCase();
            this.logger.debug("Indexing {} with id {}...", indexType, entity.getId());   
            IndexRequestBuilder indexRequestbuilder = this.client.prepareIndex( indexName, indexType, indexId);  
            indexRequestbuilder.setSource(builder.map(source));  
            // setting tenant as parent of product or similar entity - creation of child index for a given parent. 
            if (tenant != null && !Tenant.class.isAssignableFrom(entity.getClass()) ) {  
            	// This statement causes the hell - java.lang.IllegalArgumentException: Can't specify parent if no parent field has been configured 
                indexRequestbuilder.setParent(parentId);                  	            
            } 
            IndexResponse response = indexRequestbuilder.execute().actionGet();   
        }
    } catch (Exception e) {
        throw new SearchEngineException("Failed to index entity", e);
    }
}

(David Pilato) #2

Please format the code (I updated your post).

It means that your mapping is incorrect. You have to check that. Look at https://www.elastic.co/guide/en/elasticsearch/reference/2.2/mapping-parent-field.html#mapping-parent-field


(Amal Saha) #3

Hello dadoonet,
Thanks for your comment.

I already inserted parent index. This part of code is NOT shown above. Parent index need not have any knowledge of child index. I am having problem at the time inserting child index, using Java API. I take the ID of parent index created earlier and use the line below to associate the parent ID at the time of creation of child index.
indexRequestbuilder.setParent(parentId);

Detailed code is given in original post.

You raised point about mapping of data, but I have having some problem understanding it with the example in the link. In the link, the example inserts child index and parent index at the same time. But in my case, parent index already exists.

May I request you to comment further? Also it would be great if you comment on the code thru which I set parent ID in the builder.

Thanks and Regards,
Amal


(David Pilato) #4

What is your mapping for the children docs?


(Amal Saha) #5

Hi dadoonet,

Thanks again.

Here is the child mapping:

Best Regards,
Amal

{
"site":{"api_url": "http://localhost:8080/api/tenant/", "properties":{"addons": "Association of [null]",…},
"api_url": "http://localhost:8080/api//products/easydemoProd120",
"collections":[],
"properties":{
"mealDescriptionInVenue": "this meal is described above.",
"addons": "Association of [{}]",
"taxes":{"vat": "0.1"},
"minOrderInSalesUnit": 1,
"classificationMasterId": null,
"vegNonveg": "Nonveg",
"todaysmenuAvailDateAsJsonStrng": null,
"featuredCollection": "Association of [null]",
"collections": "Association of [null]",
"price": 100,
"classificationAsJsonString": null,
"stock": 200,
"localizedVersions": null,
"venueAddress": "#475 phase -5",
"todaysMenuStartDate": "2016-01-06",
"todMenuAvailDateApiObject": "org.mayocat.accounts.model.TodMenuAvailDateApiObject@4c17d623",
"brandName": "Punjabi",
"fiber": 0.06,
"productHashTag": null,
"rankProfile": "bronze",
"prodtDiscAndTax": null,
"weight": null,
"merchant": "easy-bake",
"itemPriority": 0,
"spicy": null,
"creationDate": "2015-12-02T14:13:58.842Z",
"minPersonsForVenue": 10,
"classification": "segmentL1=RESTAURANT, familyL2=MEAL, classL3=NONVEG, categoryL4=DINNER",
"flavor": "cheese",
"sodium": 0.07,
"productTopupAsJsonStrng": null,
"todaysMenuEndDate": "2016-08-30",
"salesUnit": "piece",
"productPackageType": "BASIC",
"productPackage": "org.mayocat.accounts.model.ProductPackageApiObject@4f604f72",
"sugar": 0.03,
"containnuts": null,
"classificationL2": "MEAL",
"onShelf": true,
"classificationL3": "NONVEG",
"classificationL4": "DINNER",
"potassium": 0.04,
"vailDatesForTodaysMenu": "org.mayocat.accounts.model.TodMenuAvailDateApiObject@4c17d623",
"classificationL1": "RESTAURANT",
"description": "",
"cold": "N",
"optionsTopups": "org.mayocat.accounts.model.ProductTopupsOptionsApiObject@4e63791b",
"title": "easydemoProd120",
"hot": "Y",
"itemGroupId": 0,
"manufacturer": "panjabi-tadka",
"ingredients": "chilli,salt",
"productType": "todays_menu",
"maxPersonsForVenue": 50,
"pricePerMealInVenue": 50,
"adhocEventTypeId": 0,
"calories": 20,
"saturatedFat": 0.09,
"productPackageAsJsonString": null,
"classificationAsJsonStringForOrderItem": null
},
"url": "http://localhost:8080/products/easydemoProd120",
"slug": "easydemoProd120"
}


(David Pilato) #6

This is not a mapping.

BTW please format your code


(Amal Saha) #7

Hi David,

Thanks. Here are parent and child mappings.

Regards,
Amal

parent mpping:

{
"_index": "entities",
"_type": "tenant",
"_id": "6643ee51-601f-4988-bfd6-1ab33a5c6294",
"_score": 1,
"_source":{
"api_url": “http://localhost:8080/api/tenant/",
"properties":{
"addons": "Association of [null]",
"defaultHost": null,
"name": "Easy Bake"
},
"url": "http://localhost:8080",
"slug": "easy-bake"
}
}

Child Mapping:

{
"_index": "entities",
"_type": "product",
"_id": "a2de02f6-7539-4f24-9ffa-7c5e48938c82",
"_score": 1,
"_routing": “6643ee51-601f-4988-bfd6-1ab33a5c6294",
"_source":{
"site":{"api_url": "http://localhost:8080/api/tenant/", "properties":{"addons": "Association of [null]",…},
"api_url": “http://localhost:8080/api//products/easydemoProd120",
"properties": {
"mealDescriptionInVenue": "this meal is described above.",
"vegNonveg": "Nonveg",
"todaysmenuAvailDateAsJsonStrng": null,
"featuredCollection": "Association of [null]",
"collections": "Association of [null]",
"price": 100,
"classificationAsJsonString": null,
"stock": 200,
"localizedVersions": null,
"venueAddress": "#475 phase -5",
"todaysMenuStartDate": "2016-01-06",
"minPersonsForVenue": 10,
"flavor": "cheese",
"sodium": 0.07,
"calories": 20,
"saturatedFat": 0.09
},
"url": "http://localhost:8080/products/easydemoProd120",
"slug": "easydemoProd120"
}
}


(Amal Saha) #8

Hello David,
Look forward to comments. The issue is not yet resolved.

Regards,
Amal


(David Pilato) #9

I'm still waiting for a mapping and for formatted content.


(Amal Saha) #10

Hi David,
Thanks.

I have some problem in understanding what exactly you mean by mapping. In my code, I have a map called mapping, which is used to set the mapping of index as given below:

          Map<String, Object> mapping = generator.generateMapping(); 

          ListenableActionFuture<PutMappingResponse> future = client.admin().indices()
                    .preparePutMapping("entities")
                    .setType(type)
                    .setSource(mapping)
                    .execute();

If that is the definition of mapping that you are referring to, here are the mappings, i.e., (key, value) pairs of parent and child:

parent mapping:
tenant,{properties={addons={properties={platform={properties={}}}}, properties={properties={name={type=string}}}, slug={index=not_analyzed, type=string}}}

child mapping:
product,{properties={site={properties={addons={properties={platform={properties={}}}}, properties={properties={name={type=string}}}, slug={index=not_analyzed, type=string}}}, addons={properties={platform={properties={}}}}, properties={properties={description={type=string}, onShelf={type=boolean}, price={type=double}, stock={type=long}, title={type=string}}}, slug={index=not_analyzed, type=string}}}

Thanks and Regards,
Amal


(system) #11