@KeywordField is causing bad elastic search json query

Hello,

I was analysing a generated ES query with hsearch. And the sort generated part is ambigous (it does’nt prevent to work but I don’t understand this generation) :

{
"query":
{...
},
	"sort": [
		{
			"typeSort": {
				"order": "asc",
				"unmapped_type": "keyword"
			}
		}
	]}
}

What the line "unmapped_type": "keyword" is doing here ? Indeed the sort field is on a @KeywordField, here the mapping for each index the search is operating :

@XmlRootElement(name = "ActePrive")
@Entity
@Indexed
@PrimaryKeyJoinColumn(name = "ID")
@Inheritance(strategy = InheritanceType.JOINED)
@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)
public class ActePrive extends BasicActePrive implements HasRedacteur, ISearchableParapheur, IQueryableParapheur, ISearchableFormalites, IEntityIndexed {

@Override
    @Transient
    @KeywordField(name = SearchableParapheurIndexed.TYPE_SORT, sortable = Sortable.YES)
    @IndexingDependency(
            reindexOnUpdate = ReindexOnUpdate.NO
    )
    public String getParapheurType() {
        return "MICEN";
    }
}

The sort is concerning the field SearchableParapheurIndexed.TYPE_SORT adding it simply to the query :

@Override
    protected SortFinalStep sortByField(ElasticsearchSearchSortFactory f) {
 FieldSortOptionsStep sortField = f.field(DATE_MODIFICATION);
        switch (RechercheParapheurChoixOrderBy.class.cast(configuration.getOrderBy().toChoixOrderBy(RechercheParapheurChoixOrderBy.class))) {
        case TYPE:
                sortField = f.field(TYPE_SORT);
            default:
                break;
        }

        if (RechercheChoixOrderDirection.ASC.equals(configuration.getOrderDirection().toChoixOrderDirection())) {
            return f.composite().add((SortFinalStep) sortField.asc());
        } else {
            return f.composite().add((SortFinalStep) sortField.desc());
        }

Any idea ?

Thanks.

unmapped_type doesn’t mean the field is not mapped; it means “if the field is not mapped, here’s the type Elasticsearch should assume”.

This is to support multi-index queries where a targeted field only exists in some of the indexes. In that case Elasticsearch needs us to spell out the type of the field so that it can work on those indexes that don’t have this field.

See HSEARCH-4173 and the fix.

And when you’re targeting a single index, well… unmapped_type simply doesn’t hurt.

EDIT: Actually I just checked, and unmapped_type is only added when targeting multiple indexes; so you’re probably targeting multiple indexes. But even if you’re targeting multiple indexes and they all define this field, unmapped_type doesn’t hurt.

ok I understood. Indeed, I query on multi indexes. I don’t see which indexes doesn’t have this field.

Here the debugger output, showing the 5 requesting indexes :

And the indexed entites with the field SearchableParapheurIndexed.TYPE_SORT index :

depot-read index :

@Entity
@Indexed
public class Depot extends BasicDepot implements IArchivable, ISearchableParapheur, IQueryableParapheur, ISearchableFormalites, IEntityIndexed {

@Override
	@Transient
	@KeywordField(name = SearchableParapheurIndexed.TYPE_SORT, sortable = Sortable.YES)
	@IndexingDependency(derivedFrom = {
			@ObjectPath(@PropertyValue(propertyName = PROJECT))
	})
	public String getParapheurType() {
		return getProject().getLibelle();
	}


}

acteprive-read index :

@Entity
@Indexed
@PrimaryKeyJoinColumn(name = "ID")
@Inheritance(strategy = InheritanceType.JOINED)
@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)
public class ActePrive extends BasicActePrive implements HasRedacteur, ISearchableParapheur, IQueryableParapheur, ISearchableFormalites, IEntityIndexed {

@Override
    @Transient
    @KeywordField(name = SearchableParapheurIndexed.TYPE_SORT, sortable = Sortable.YES)
    @IndexingDependency(
            reindexOnUpdate = ReindexOnUpdate.NO
    )
    public String getParapheurType() {
        return "MICEN";
    }

}

mentionmicen-read index :

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@Indexed
public class MentionMicen
		extends BasicMentionMicen implements Comparable<MentionMicen>, IArchivable, ISearchableParapheur, IQueryableParapheur, IEntityIndexed {

@Override
	@Transient
	@KeywordField(name = SearchableParapheurIndexed.TYPE_SORT, sortable = Sortable.YES)
	@IndexingDependency(
			reindexOnUpdate = ReindexOnUpdate.NO
	)
	public String getParapheurType() {
		return "MICEN";
	}
}

acteparticipation-read :

@Entity
@Indexed
public class ActeParticipation extends BasicActeParticipation implements IArchivable, ISearchableParapheur, IEntityIndexed {

@Transient
	@KeywordField(name = SearchableParapheurIndexed.TYPE_SORT, sortable = Sortable.YES)
	@IndexingDependency(
			reindexOnUpdate = ReindexOnUpdate.NO
	)
	@Override
	public String getParapheurType() {
		return "MICEN";
	}


}

actedocument-read :

@Entity
@PrimaryKeyJoinColumn(name = "ID")
@Inheritance(strategy = InheritanceType.JOINED)
@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)
public class ActeDocument extends BasicActeDocument {

}

@MappedSuperclass
public abstract class BasicActeDocument extends **ActePrive** {
}

You will notice that for actedocument-read, the index is inherited. And ActeDocument is not indexed with @Indexed because when ActePrive is indexing, I already have documents in ES mapping document of type actedocument-0001 :

I suppose the problem is that the sort is not correct so, if the field to sort on is missing…

Elasticsearch supports sorting on fields with missing values. So sorting on a field that is missing in some target indexes is most definitely correct.

unmapped_type is added regardless of whether the field is missing in some indexes or not. Just in case, and also because I was too lazy to go through all the necessary checks a more precise solution would involve.

As I said:

ok. I think that I upgraded from hsearch-orm-mapper 6.0.Final to 6.0.8.Final … these unmapped_type is new since then ? I was anxious with that added attribut :smiley:

HSEARCH-4173 was fixed in version 6.0.3.Final.

I didn’t have this unmapped_type before, then all explain. All’s well That ends well :upside_down_face:

Thanks you.