protected void applySort(SearchRequestBuilder q) {
for (SortContainer sortContainer : getParameters().getSortContainers()) {
SortOrder esOrder = sortContainer.direction == SortDirection.ASCENDING ? SortOrder.ASC : SortOrder.DESC;
if (Element.ID_PROPERTY_NAME.equals(sortContainer.propertyName)) {
q.addSort("_uid", esOrder);
} else if (Edge.LABEL_PROPERTY_NAME.equals(sortContainer.propertyName)) {
q.addSort(Elasticsearch5SearchIndex.EDGE_LABEL_FIELD_NAME, esOrder);
} else {
PropertyDefinition propertyDefinition = getGraph().getPropertyDefinition(sortContainer.propertyName);
if (propertyDefinition == null) {
continue;
}
if (!getSearchIndex().isPropertyInIndex(getGraph(), sortContainer.propertyName)) {
continue;
}
if (!propertyDefinition.isSortable()) {
throw new MemgraphException("Cannot sort on non-sortable fields");
}
String[] propertyNames = getPropertyNames(propertyDefinition.getPropertyName());
if (propertyNames.length > 1) {
String scriptSrc = "def fieldValues = []; for (def fieldName : params.fieldNames) { fieldValues.addAll(doc[fieldName].values); } " +
"if (params.esOrder == 'asc') { Collections.sort(fieldValues); } else { Collections.sort(fieldValues, Collections.reverseOrder()); }" +
"if (params.dataType == 'String') { return fieldValues; } else { return fieldValues.length > 0 ? fieldValues[0] : (params.esOrder == 'asc' ? Integer.MAX_VALUE : Integer.MIN_VALUE); }";
List fieldNames = Arrays.stream(propertyNames).map(propertyName ->
propertyName + (propertyDefinition.getDataType() == String.class ? Elasticsearch5SearchIndex.EXACT_MATCH_PROPERTY_NAME_SUFFIX : "")
).collect(Collectors.toList());
HashMap scriptParams = new HashMap<>();
scriptParams.put("fieldNames", fieldNames);
scriptParams.put("esOrder", esOrder == SortOrder.DESC ? "desc" : "asc");
scriptParams.put("dataType", propertyDefinition.getDataType().getSimpleName());
Script script = new Script(ScriptType.INLINE, "painless", scriptSrc, scriptParams);
ScriptSortBuilder.ScriptSortType sortType = propertyDefinition.getDataType() == String.class ? ScriptSortBuilder.ScriptSortType.STRING : ScriptSortBuilder.ScriptSortType.NUMBER;
q.addSort(SortBuilders.scriptSort(script, sortType)
.order(esOrder)
.sortMode(esOrder == SortOrder.DESC ? SortMode.MAX : SortMode.MIN));
} else {
String sortField = propertyNames[0];
if (propertyDefinition.getDataType() == String.class) {
sortField += Elasticsearch5SearchIndex.EXACT_MATCH_PROPERTY_NAME_SUFFIX;
}
q.addSort(sortField, esOrder);
}
}
}
}