use of com.yahoo.search.query.Sorting in project vespa by vespa-engine.
the class UniqueGroupingSearcher method dedupe.
/**
* Until we can use the grouping pagination features in 5.1, we'll have to support offset
* by simply requesting and discarding hit #0 up to hit #offset.
*/
private static Result dedupe(Query query, Execution execution, String dedupField) {
Sorting sorting = query.getRanking().getSorting();
if (sorting != null && sorting.fieldOrders().size() > 1) {
query.trace("Can not use grouping for deduping with multi-level sorting.", 3);
// we'd ever want to actually use it (and a bit harder to implement as well).
return execution.search(query);
}
int hits = query.getHits();
int offset = query.getOffset();
int groupingHits = hits + offset;
GroupingRequest groupingRequest = GroupingRequest.newInstance(query);
groupingRequest.setRootOperation(buildGroupingExpression(dedupField, groupingHits, query.getPresentation().getSummary(), sorting));
query.setHits(0);
query.setOffset(0);
Result result = execution.search(query);
// query could have changed further down in the chain
query = result.getQuery();
query.setHits(hits);
query.setOffset(offset);
Group root = groupingRequest.getResultGroup(result);
if (null == root) {
String msg = "Result group not found for deduping grouping request, returning empty result.";
query.trace(msg, 3);
log.log(LogLevel.WARNING, msg);
throw new IllegalStateException("Failed to produce deduped result set.");
}
// hide our tracks
result.hits().remove(root.getId().toString());
GroupList resultGroups = root.getGroupList(dedupField);
if (resultGroups == null) {
query.trace("Deduping grouping request returned no hits, returning empty result.", 3);
return result;
}
// Make sure that .addAll() doesn't re-order the hits we copy from the grouping
// framework. The groups are already in the order they should be.
result.hits().setOrderer(NOP_ORDERER);
result.hits().addAll(getRequestedHits(resultGroups, offset, hits));
Long countField = (Long) root.getField(LABEL_COUNT);
long count = countField != null ? countField : 0;
result.setTotalHitCount(count);
return result;
}
use of com.yahoo.search.query.Sorting in project vespa by vespa-engine.
the class Organizer method assignOrderer.
private void assignOrderer(Section section, Resolution resolution, List<String> sourceList, HitGroup group) {
if (section.getOrder() == null) {
// then sort by relevance, source
group.setOrderer(new HitSortOrderer(new RelevanceComparator(new SourceOrderComparator(sourceList))));
return;
}
// replace a source field comparison by one which knows the source list order
// and add default sorting at the end if necessary
Sorting sorting = section.getOrder();
int rankIndex = -1;
int sourceIndex = -1;
for (int i = 0; i < sorting.fieldOrders().size(); i++) {
Sorting.FieldOrder order = sorting.fieldOrders().get(i);
if ("[relevance]".equals(order.getFieldName()) || "[rank]".equals(order.getFieldName()))
rankIndex = i;
else if (order.getFieldName().equals("[source]"))
sourceIndex = i;
}
ChainableComparator comparator;
Sorting beforeSource = null;
Sorting afterSource = null;
if (sourceIndex >= 0) {
// replace alphabetical sorting on source by sourceList order sorting
if (// sort fields before the source
sourceIndex > 0)
beforeSource = new Sorting(new ArrayList<>(sorting.fieldOrders().subList(0, sourceIndex)));
if (// sort fields after the source
sorting.fieldOrders().size() > sourceIndex + 1)
afterSource = new Sorting(new ArrayList<>(sorting.fieldOrders().subList(sourceIndex + 1, sorting.fieldOrders().size() + 1)));
comparator = new SourceOrderComparator(sourceList, FieldComparator.create(afterSource));
if (beforeSource != null)
comparator = new FieldComparator(beforeSource, comparator);
} else if (rankIndex >= 0) {
// add sort by source at the end
comparator = new FieldComparator(sorting, new SourceOrderComparator(sourceList));
} else {
// add sort by rank,source at the end
comparator = new FieldComparator(sorting, new RelevanceComparator(new SourceOrderComparator(sourceList)));
}
group.setOrderer(new HitSortOrderer(comparator));
}
use of com.yahoo.search.query.Sorting in project vespa by vespa-engine.
the class ValidateSortingSearcher method validate.
private ErrorMessage validate(Query query) {
Sorting sorting = query.getRanking().getSorting();
List<Sorting.FieldOrder> l = (sorting != null) ? sorting.fieldOrders() : null;
if (l == null) {
return null;
}
Map<String, AttributesConfig.Attribute> names = getAttributeNames();
if (names == null) {
return null;
}
String queryLocale = null;
if (query.getModel().getLocale() != null) {
queryLocale = query.getModel().getLocale().toString();
}
for (Sorting.FieldOrder f : l) {
String name = f.getFieldName();
if ("[rank]".equals(name) || "[docid]".equals(name)) {
// built-in constants - ok
} else if (names.containsKey(name)) {
AttributesConfig.Attribute attrConfig = names.get(name);
if (attrConfig != null) {
if (f.getSortOrder() == Sorting.Order.UNDEFINED) {
f.setAscending(attrConfig.sortascending());
}
if (f.getSorter().getClass().equals(Sorting.AttributeSorter.class)) {
// This indicates that it shall use default.
if ((attrConfig.datatype() == AttributesConfig.Attribute.Datatype.STRING)) {
if (attrConfig.sortfunction() == AttributesConfig.Attribute.Sortfunction.UCA) {
String locale = attrConfig.sortlocale();
if (locale == null || locale.isEmpty()) {
locale = queryLocale;
}
// can only use UcaSorter if we have knowledge about wanted locale
if (locale != null) {
f.setSorter(new Sorting.UcaSorter(name, locale, Sorting.UcaSorter.Strength.UNDEFINED));
} else {
// wanted UCA but no locale known, so use lowercase as fallback
f.setSorter(new Sorting.LowerCaseSorter(name));
}
} else if (attrConfig.sortfunction() == AttributesConfig.Attribute.Sortfunction.LOWERCASE) {
f.setSorter(new Sorting.LowerCaseSorter(name));
} else if (attrConfig.sortfunction() == AttributesConfig.Attribute.Sortfunction.RAW) {
f.setSorter(new Sorting.RawSorter(name));
} else {
// default if no config found for this string attribute
f.setSorter(new Sorting.LowerCaseSorter(name));
}
}
}
if (f.getSorter() instanceof Sorting.UcaSorter) {
Sorting.UcaSorter sorter = (Sorting.UcaSorter) f.getSorter();
String locale = sorter.getLocale();
if (locale == null || locale.isEmpty()) {
// first fallback
locale = attrConfig.sortlocale();
}
if (locale == null || locale.isEmpty()) {
// second fallback
locale = queryLocale;
}
// final fallback
if (locale == null || locale.isEmpty()) {
locale = "en_US";
}
Sorting.UcaSorter.Strength strength = sorter.getStrength();
if (sorter.getStrength() == Sorting.UcaSorter.Strength.UNDEFINED) {
strength = config2Strength(attrConfig.sortstrength());
}
if ((sorter.getStrength() == Sorting.UcaSorter.Strength.UNDEFINED) || (sorter.getLocale() == null) || sorter.getLocale().isEmpty()) {
sorter.setLocale(locale, strength);
}
}
} else {
return ErrorMessage.createInvalidQueryParameter("The cluster " + getClusterName() + " has attribute config for field: " + name);
}
} else {
return ErrorMessage.createInvalidQueryParameter("The cluster " + getClusterName() + " has no sortable attribute named: " + name);
}
}
return null;
}
use of com.yahoo.search.query.Sorting in project vespa by vespa-engine.
the class SortingDegrader method setDegradation.
private void setDegradation(Query query) {
query.trace("Using sorting degrading for performance - totalHits will be wrong. " + "Turn off with sorting.degrading=false.", 2);
// ensured above
Sorting.FieldOrder primarySort = query.getRanking().getSorting().fieldOrders().get(0);
MatchPhase matchPhase = query.getRanking().getMatchPhase();
matchPhase.setAttribute(primarySort.getFieldName());
matchPhase.setAscending(primarySort.getSortOrder() == Sorting.Order.ASCENDING);
if (matchPhase.getMaxHits() == null)
matchPhase.setMaxHits(decideDefaultMaxHits(query));
}
use of com.yahoo.search.query.Sorting in project vespa by vespa-engine.
the class YqlParser method fetchSorting.
@NonNull
private OperatorNode<?> fetchSorting(OperatorNode<?> ast) {
if (ast.getOperator() != SequenceOperator.SORT)
return ast;
List<FieldOrder> sortingInit = new ArrayList<>();
List<OperatorNode<?>> sortArguments = ast.getArgument(1);
for (OperatorNode<?> op : sortArguments) {
OperatorNode<ExpressionOperator> fieldNode = op.<OperatorNode<ExpressionOperator>>getArgument(0);
String field = fetchFieldRead(fieldNode);
String locale = getAnnotation(fieldNode, SORTING_LOCALE, String.class, null, "locale used by sorting function");
String function = getAnnotation(fieldNode, SORTING_FUNCTION, String.class, null, "sorting function for the specified attribute");
String strength = getAnnotation(fieldNode, SORTING_STRENGTH, String.class, null, "strength for sorting function");
AttributeSorter sorter;
if (function == null) {
sorter = new AttributeSorter(field);
} else if (Sorting.LOWERCASE.equals(function)) {
sorter = new LowerCaseSorter(field);
} else if (Sorting.RAW.equals(function)) {
sorter = new RawSorter(field);
} else if (Sorting.UCA.equals(function)) {
if (locale != null) {
UcaSorter.Strength ucaStrength = UcaSorter.Strength.UNDEFINED;
if (strength != null) {
if (Sorting.STRENGTH_PRIMARY.equalsIgnoreCase(strength)) {
ucaStrength = UcaSorter.Strength.PRIMARY;
} else if (Sorting.STRENGTH_SECONDARY.equalsIgnoreCase(strength)) {
ucaStrength = UcaSorter.Strength.SECONDARY;
} else if (Sorting.STRENGTH_TERTIARY.equalsIgnoreCase(strength)) {
ucaStrength = UcaSorter.Strength.TERTIARY;
} else if (Sorting.STRENGTH_QUATERNARY.equalsIgnoreCase(strength)) {
ucaStrength = UcaSorter.Strength.QUATERNARY;
} else if (Sorting.STRENGTH_IDENTICAL.equalsIgnoreCase(strength)) {
ucaStrength = UcaSorter.Strength.IDENTICAL;
} else {
throw newUnexpectedArgumentException(function, Sorting.STRENGTH_PRIMARY, Sorting.STRENGTH_SECONDARY, Sorting.STRENGTH_TERTIARY, Sorting.STRENGTH_QUATERNARY, Sorting.STRENGTH_IDENTICAL);
}
sorter = new UcaSorter(field, locale, ucaStrength);
} else {
sorter = new UcaSorter(field, locale, ucaStrength);
}
} else {
sorter = new UcaSorter(field);
}
} else {
throw newUnexpectedArgumentException(function, "lowercase", "raw", "uca");
}
switch((SortOperator) op.getOperator()) {
case ASC:
sortingInit.add(new FieldOrder(sorter, Order.ASCENDING));
break;
case DESC:
sortingInit.add(new FieldOrder(sorter, Order.DESCENDING));
break;
default:
throw newUnexpectedArgumentException(op.getOperator(), SortOperator.ASC, SortOperator.DESC);
}
}
sorting = new Sorting(sortingInit);
return ast.getArgument(0);
}
Aggregations