Skip to content

Commit

Permalink
Use higher abstraction SynonymImpactsSource in CombinedFieldQuery
Browse files Browse the repository at this point in the history
  • Loading branch information
zacharymorn committed Dec 8, 2021
1 parent cbbd28b commit 502d44e
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 84 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.lucene.search;

import java.io.IOException;
import java.util.List;
import org.apache.lucene.index.Impact;
import org.apache.lucene.index.Impacts;
import org.apache.lucene.index.ImpactsEnum;
import org.apache.lucene.index.ImpactsSource;

public class SynonymImpactsSource implements ImpactsSource {

private final ImpactsEnum[] impactsEnums;
private final Impacts[] impacts;
private final float[] boosts;
private Impacts lead;

public SynonymImpactsSource(ImpactsEnum[] impactsEnums, float[] boosts) {
this.impactsEnums = impactsEnums;
this.boosts = boosts;
this.impacts = new Impacts[impactsEnums.length];
}

@Override
public Impacts getImpacts() throws IOException {
// Use the impacts that have the lower next boundary as a lead.
// It will decide on the number of levels and the block boundaries.
if (lead == null) {
Impacts tmpLead = null;
for (int i = 0; i < impactsEnums.length; ++i) {
impacts[i] = impactsEnums[i].getImpacts();
if (tmpLead == null || impacts[i].getDocIdUpTo(0) < tmpLead.getDocIdUpTo(0)) {
tmpLead = impacts[i];
}
}
lead = tmpLead;
}
return new Impacts() {

@Override
public int numLevels() {
// Delegate to the lead
return lead.numLevels();
}

@Override
public int getDocIdUpTo(int level) {
// Delegate to the lead
return lead.getDocIdUpTo(level);
}

@Override
public List<Impact> getImpacts(int level) {
final int docIdUpTo = getDocIdUpTo(level);
return ImpactsMergingUtils.mergeImpactsPerField(
impactsEnums, impacts, boosts, docIdUpTo, false);
}
};
}

@Override
public void advanceShallow(int target) throws IOException {
for (ImpactsEnum impactsEnum : impactsEnums) {
if (impactsEnum.docID() < target) {
impactsEnum.advanceShallow(target);
}
}
}

public Impacts[] impacts() {
return impacts;
}
}
50 changes: 1 addition & 49 deletions lucene/core/src/java/org/apache/lucene/search/SynonymQuery.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import org.apache.lucene.index.Impact;
import org.apache.lucene.index.Impacts;
import org.apache.lucene.index.ImpactsEnum;
import org.apache.lucene.index.ImpactsSource;
import org.apache.lucene.index.IndexReader;
Expand Down Expand Up @@ -342,53 +340,7 @@ public boolean isCacheable(LeafReaderContext ctx) {
/** Merge impacts for multiple synonyms. */
static ImpactsSource mergeImpacts(ImpactsEnum[] impactsEnums, float[] boosts) {
assert impactsEnums.length == boosts.length;
return new ImpactsSource() {

@Override
public Impacts getImpacts() throws IOException {
final Impacts[] impacts = new Impacts[impactsEnums.length];
// Use the impacts that have the lower next boundary as a lead.
// It will decide on the number of levels and the block boundaries.
Impacts tmpLead = null;
for (int i = 0; i < impactsEnums.length; ++i) {
impacts[i] = impactsEnums[i].getImpacts();
if (tmpLead == null || impacts[i].getDocIdUpTo(0) < tmpLead.getDocIdUpTo(0)) {
tmpLead = impacts[i];
}
}
final Impacts lead = tmpLead;
return new Impacts() {

@Override
public int numLevels() {
// Delegate to the lead
return lead.numLevels();
}

@Override
public int getDocIdUpTo(int level) {
// Delegate to the lead
return lead.getDocIdUpTo(level);
}

@Override
public List<Impact> getImpacts(int level) {
final int docIdUpTo = getDocIdUpTo(level);
return ImpactsMergingUtils.mergeImpactsPerField(
impactsEnums, impacts, boosts, docIdUpTo, false);
}
};
}

@Override
public void advanceShallow(int target) throws IOException {
for (ImpactsEnum impactsEnum : impactsEnums) {
if (impactsEnum.docID() < target) {
impactsEnum.advanceShallow(target);
}
}
}
};
return new SynonymImpactsSource(impactsEnums, boosts);
}

private static class SynonymScorer extends Scorer {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
import org.apache.lucene.search.QueryVisitor;
import org.apache.lucene.search.ScoreMode;
import org.apache.lucene.search.Scorer;
import org.apache.lucene.search.SynonymImpactsSource;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TermScorer;
import org.apache.lucene.search.TermStatistics;
Expand Down Expand Up @@ -491,49 +492,32 @@ static ImpactsSource mergeImpacts(
Map<String, ImpactsEnum[]> fieldImpactsEnum, Map<String, float[]> fieldWeights) {

return new ImpactsSource() {
final Map<String, Impacts[]> fieldImpacts = new HashMap<>();
Map<String, Impacts> leadingImpactsPerField = null;
Map<String, SynonymImpactsSource> fieldImpactsSource = null;

@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.

if (leadingImpactsPerField == null) {
leadingImpactsPerField = new HashMap<>(fieldImpactsEnum.size());
fieldImpacts.clear();

if (fieldImpactsSource == null) {
fieldImpactsSource = new HashMap<>();
for (Map.Entry<String, ImpactsEnum[]> e : fieldImpactsEnum.entrySet()) {
String field = e.getKey();
ImpactsEnum[] impactsEnums = e.getValue();
Impacts[] impacts = new Impacts[impactsEnums.length];
fieldImpacts.put(field, impacts);

Impacts tmpLead = null;
// find the impact that has the lowest next boundary for this field
for (int i = 0; i < impactsEnums.length; ++i) {
Impacts currentImpacts = impactsEnums[i].getImpacts();
impacts[i] = currentImpacts;

if (tmpLead == null || currentImpacts.getDocIdUpTo(0) < tmpLead.getDocIdUpTo(0)) {
tmpLead = currentImpacts;
}
}

leadingImpactsPerField.put(field, tmpLead);
SynonymImpactsSource source =
new SynonymImpactsSource(e.getValue(), fieldWeights.get(e.getKey()));
fieldImpactsSource.put(e.getKey(), source);
}
}

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());
for (SynonymImpactsSource s : fieldImpactsSource.values()) {
try {
result = Math.max(result, s.getImpacts().numLevels());
} catch (IOException e) {
// nocommit to be handled
e.printStackTrace();
}
}

return result;
Expand All @@ -544,15 +528,26 @@ 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));
for (SynonymImpactsSource s : fieldImpactsSource.values()) {
Impacts impacts;
try {
impacts = s.getImpacts();
if (impacts.numLevels() > level) {
result = Math.min(result, impacts.getDocIdUpTo(level));
}
} catch (IOException e) {
// nocommit to be handled
e.printStackTrace();
}
}

return result;
}

// this can't loop over each field's SynonymImpactsSource.getImpacts().getImpacts(level)
// and then combine impacts,
// as docIdUpTo of each SynonymImpactsSource.getImpacts().getImpacts(level) might be
// different for the same level
@Override
public List<Impact> getImpacts(int level) {
final int docIdUpTo = getDocIdUpTo(level);
Expand All @@ -571,7 +566,7 @@ private Map<String, List<Impact>> getMergedImpactsPerField(int docIdUpTo) {
List<Impact> mergedImpacts =
ImpactsMergingUtils.mergeImpactsPerField(
impactsEnums,
fieldImpacts.get(field),
fieldImpactsSource.get(field).impacts(),
fieldWeights.get(field),
docIdUpTo,
true);
Expand Down Expand Up @@ -628,7 +623,8 @@ public void advanceShallow(int target) throws IOException {
}
}
}
leadingImpactsPerField = null;

fieldImpactsSource = null;
}
};
}
Expand Down

0 comments on commit 502d44e

Please sign in to comment.