mirror of https://github.com/apache/lucene.git
SOLR-15049: Add TopLevelJoinQuery optimization for 'self-joins' (#2146)
This commit is contained in:
parent
d905a7ba8e
commit
8b272a0960
|
@ -230,6 +230,8 @@ Optimizations
|
|||
---------------------
|
||||
* SOLR-14975: Optimize CoreContainer.getAllCoreNames, getLoadedCoreNames and getCoreDescriptors. (Bruno Roustant)
|
||||
|
||||
* SOLR-15049: Optimize same-core, same-field joins in TopLevelJoinQuery (Jason Gerlowski)
|
||||
|
||||
Bug Fixes
|
||||
---------------------
|
||||
* SOLR-14946: Fix responseHeader being returned in response when omitHeader=true and EmbeddedSolrServer is used
|
||||
|
|
|
@ -90,7 +90,7 @@ public class JoinQParserPlugin extends QParserPlugin {
|
|||
@Override
|
||||
Query makeFilter(QParser qparser, JoinQParserPlugin plugin) throws SyntaxError {
|
||||
final JoinParams jParams = parseJoin(qparser);
|
||||
final JoinQuery q = new TopLevelJoinQuery(jParams.fromField, jParams.toField, jParams.fromCore, jParams.fromQuery);
|
||||
final JoinQuery q = createTopLevelJoin(jParams);
|
||||
q.fromCoreOpenTime = jParams.fromCoreOpenTime;
|
||||
return q;
|
||||
}
|
||||
|
@ -99,6 +99,18 @@ public class JoinQParserPlugin extends QParserPlugin {
|
|||
Query makeJoinDirectFromParams(JoinParams jParams) {
|
||||
return new TopLevelJoinQuery(jParams.fromField, jParams.toField, null, jParams.fromQuery);
|
||||
}
|
||||
|
||||
private JoinQuery createTopLevelJoin(JoinParams jParams) {
|
||||
if (isSelfJoin(jParams)) {
|
||||
return new TopLevelJoinQuery.SelfJoin(jParams.fromField, jParams.fromQuery);
|
||||
}
|
||||
return new TopLevelJoinQuery(jParams.fromField, jParams.toField, jParams.fromCore, jParams.fromQuery);
|
||||
}
|
||||
|
||||
private boolean isSelfJoin(JoinParams jparams) {
|
||||
return jparams.fromCore == null &&
|
||||
(jparams.fromField != null && jparams.fromField.equals(jparams.toField));
|
||||
}
|
||||
},
|
||||
crossCollection {
|
||||
@Override
|
||||
|
|
|
@ -162,7 +162,7 @@ public class TopLevelJoinQuery extends JoinQuery {
|
|||
return fromOrdBitSet;
|
||||
}
|
||||
|
||||
private BitsetBounds convertFromOrdinalsIntoToField(LongBitSet fromOrdBitSet, SortedSetDocValues fromDocValues,
|
||||
protected BitsetBounds convertFromOrdinalsIntoToField(LongBitSet fromOrdBitSet, SortedSetDocValues fromDocValues,
|
||||
LongBitSet toOrdBitSet, SortedSetDocValues toDocValues) throws IOException {
|
||||
long fromOrdinal = 0;
|
||||
long firstToOrd = BitsetBounds.NO_MATCHES;
|
||||
|
@ -208,7 +208,7 @@ public class TopLevelJoinQuery extends JoinQuery {
|
|||
return -(low + 1); // key not found.
|
||||
}
|
||||
|
||||
private static class BitsetBounds {
|
||||
protected static class BitsetBounds {
|
||||
public static final long NO_MATCHES = -1L;
|
||||
public final long lower;
|
||||
public final long upper;
|
||||
|
@ -218,4 +218,28 @@ public class TopLevelJoinQuery extends JoinQuery {
|
|||
this.upper = upper;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link TopLevelJoinQuery} implementation optimized for when 'from' and 'to' cores and fields match and no ordinal-
|
||||
* conversion is necessary.
|
||||
*/
|
||||
static class SelfJoin extends TopLevelJoinQuery {
|
||||
public SelfJoin(String joinField, Query subQuery) {
|
||||
super(joinField, joinField, null, subQuery);
|
||||
}
|
||||
|
||||
protected BitsetBounds convertFromOrdinalsIntoToField(LongBitSet fromOrdBitSet, SortedSetDocValues fromDocValues,
|
||||
LongBitSet toOrdBitSet, SortedSetDocValues toDocValues) throws IOException {
|
||||
|
||||
// 'from' and 'to' ordinals are identical for self-joins.
|
||||
toOrdBitSet.or(fromOrdBitSet);
|
||||
|
||||
// Calculate boundary ords used for other optimizations
|
||||
final long firstToOrd = toOrdBitSet.nextSetBit(0);
|
||||
final long lastToOrd = toOrdBitSet.prevSetBit(toOrdBitSet.length() - 1);
|
||||
return new BitsetBounds(firstToOrd, lastToOrd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue