jpountz commented on a change in pull request #418: URL: https://github.com/apache/lucene/pull/418#discussion_r750020101
########## File path: lucene/sandbox/src/java/org/apache/lucene/sandbox/search/CombinedFieldQuery.java ########## @@ -441,6 +491,273 @@ public boolean isCacheable(LeafReaderContext ctx) { } } + /** Merge impacts for combined field. */ + static ImpactsSource mergeImpacts( + Map<String, List<ImpactsEnum>> fieldsWithImpactsEnums, + Map<String, List<Impacts>> fieldsWithImpacts, + Map<String, Float> fieldWeights) { + return new ImpactsSource() { + + class SubIterator { + final Iterator<Impact> iterator; + int previousFreq; + Impact current; + + SubIterator(Iterator<Impact> iterator) { + this.iterator = iterator; + this.current = iterator.next(); + } + + void next() { + previousFreq = current.freq; + if (iterator.hasNext() == false) { + current = null; + } else { + current = iterator.next(); + } + } + } + + @Override + public Impacts getImpacts() throws IOException { + // Use the impacts that have the lower next boundary (doc id in skip entry) as a lead for + // each field + // They collectively will decide on the number of levels and the block boundaries. + Map<String, Impacts> leadingImpactsPerField = new HashMap<>(fieldsWithImpactsEnums.size()); + + for (Map.Entry<String, List<ImpactsEnum>> fieldImpacts : + fieldsWithImpactsEnums.entrySet()) { + String field = fieldImpacts.getKey(); + List<ImpactsEnum> impactsEnums = fieldImpacts.getValue(); + fieldsWithImpacts.put(field, new ArrayList<>(impactsEnums.size())); + + Impacts tmpLead = null; + // find the impact that has the lowest next boundary for this field + for (int i = 0; i < impactsEnums.size(); ++i) { + Impacts impacts = impactsEnums.get(i).getImpacts(); + fieldsWithImpacts.get(field).add(impacts); + + if (tmpLead == null || impacts.getDocIdUpTo(0) < tmpLead.getDocIdUpTo(0)) { + tmpLead = impacts; + } + } + + leadingImpactsPerField.put(field, tmpLead); + } + + return new Impacts() { + + @Override + public int numLevels() { + // max of levels across fields' impactEnums + int result = 0; + + for (Impacts impacts : leadingImpactsPerField.values()) { + result = Math.max(result, impacts.numLevels()); + } + + return result; + } + + @Override + public int getDocIdUpTo(int level) { + // min of docIdUpTo across fields' impactEnums + int result = Integer.MAX_VALUE; + + for (Impacts impacts : leadingImpactsPerField.values()) { + if (impacts.numLevels() > level) { + result = Math.min(result, impacts.getDocIdUpTo(level)); + } + } + + return result; + } Review comment: > I'm suspecting this may occur when the max score is being computed too frequently, as frequent term's skip list would be "dense" and is also used to determine upTo for max score That would make sense to me. Maybe update this class so that numLevels / getDocIdUpTo only use the impacts of the term that has the highest weight? -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: issues-unsubscr...@lucene.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org --------------------------------------------------------------------- To unsubscribe, e-mail: issues-unsubscr...@lucene.apache.org For additional commands, e-mail: issues-h...@lucene.apache.org