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-14975: Optimize CoreContainer.getAllCoreNames, getLoadedCoreNames and getCoreDescriptors. (Bruno Roustant)
|
||||||
|
|
||||||
|
* SOLR-15049: Optimize same-core, same-field joins in TopLevelJoinQuery (Jason Gerlowski)
|
||||||
|
|
||||||
Bug Fixes
|
Bug Fixes
|
||||||
---------------------
|
---------------------
|
||||||
* SOLR-14946: Fix responseHeader being returned in response when omitHeader=true and EmbeddedSolrServer is used
|
* 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
|
@Override
|
||||||
Query makeFilter(QParser qparser, JoinQParserPlugin plugin) throws SyntaxError {
|
Query makeFilter(QParser qparser, JoinQParserPlugin plugin) throws SyntaxError {
|
||||||
final JoinParams jParams = parseJoin(qparser);
|
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;
|
q.fromCoreOpenTime = jParams.fromCoreOpenTime;
|
||||||
return q;
|
return q;
|
||||||
}
|
}
|
||||||
|
@ -99,6 +99,18 @@ public class JoinQParserPlugin extends QParserPlugin {
|
||||||
Query makeJoinDirectFromParams(JoinParams jParams) {
|
Query makeJoinDirectFromParams(JoinParams jParams) {
|
||||||
return new TopLevelJoinQuery(jParams.fromField, jParams.toField, null, jParams.fromQuery);
|
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 {
|
crossCollection {
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -162,7 +162,7 @@ public class TopLevelJoinQuery extends JoinQuery {
|
||||||
return fromOrdBitSet;
|
return fromOrdBitSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
private BitsetBounds convertFromOrdinalsIntoToField(LongBitSet fromOrdBitSet, SortedSetDocValues fromDocValues,
|
protected BitsetBounds convertFromOrdinalsIntoToField(LongBitSet fromOrdBitSet, SortedSetDocValues fromDocValues,
|
||||||
LongBitSet toOrdBitSet, SortedSetDocValues toDocValues) throws IOException {
|
LongBitSet toOrdBitSet, SortedSetDocValues toDocValues) throws IOException {
|
||||||
long fromOrdinal = 0;
|
long fromOrdinal = 0;
|
||||||
long firstToOrd = BitsetBounds.NO_MATCHES;
|
long firstToOrd = BitsetBounds.NO_MATCHES;
|
||||||
|
@ -208,7 +208,7 @@ public class TopLevelJoinQuery extends JoinQuery {
|
||||||
return -(low + 1); // key not found.
|
return -(low + 1); // key not found.
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class BitsetBounds {
|
protected static class BitsetBounds {
|
||||||
public static final long NO_MATCHES = -1L;
|
public static final long NO_MATCHES = -1L;
|
||||||
public final long lower;
|
public final long lower;
|
||||||
public final long upper;
|
public final long upper;
|
||||||
|
@ -218,4 +218,28 @@ public class TopLevelJoinQuery extends JoinQuery {
|
||||||
this.upper = upper;
|
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