Exactly index sortkey with Lucene

Store sortkey as a long and implement the before and after operators
as numeric range queries.  This is a short-term hack until we have a
better idea of how to handle pagination without relying on a made up
string value stored on the change object.

Change-Id: Ibf7a8be281da8cd9e7ccc08bba600bbc2e0e962c
This commit is contained in:
Shawn Pearce
2013-06-25 19:04:25 -06:00
parent 6ef53023df
commit 3d35b823cb
5 changed files with 51 additions and 19 deletions

View File

@@ -44,6 +44,7 @@ import com.google.gerrit.server.query.QueryParseException;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.query.change.ChangeDataSource;
import com.google.gerrit.server.query.change.IndexRewriteImpl;
import com.google.gerrit.server.query.change.SortKeyPredicate;
import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.ResultSet;
@@ -52,6 +53,7 @@ import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.document.IntField;
import org.apache.lucene.document.LongField;
import org.apache.lucene.document.StringField;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
@@ -261,6 +263,8 @@ public class LuceneChangeIndex implements ChangeIndex, LifecycleListener {
return exactQuery(p);
} else if (p.getType() == FieldType.PREFIX) {
return prefixQuery(p);
} else if (p instanceof SortKeyPredicate) {
return sortKeyQuery((SortKeyPredicate) p);
} else {
throw badFieldType(p.getType());
}
@@ -285,6 +289,14 @@ public class LuceneChangeIndex implements ChangeIndex, LifecycleListener {
return new TermQuery(intTerm(p.getOperator(), value));
}
private static Query sortKeyQuery(SortKeyPredicate p) {
return NumericRangeQuery.newLongRange(
p.getField().getName(),
p.getMinValue(),
p.getMaxValue(),
true, true);
}
private static Query timestampQuery(IndexPredicate<ChangeData> p)
throws QueryParseException {
if (p instanceof TimestampRangePredicate) {
@@ -442,6 +454,10 @@ public class LuceneChangeIndex implements ChangeIndex, LifecycleListener {
for (Object value : values) {
doc.add(new IntField(name, (Integer) value, store));
}
} else if (f.getType() == FieldType.LONG) {
for (Object value : values) {
doc.add(new LongField(name, (Long) value, store));
}
} else if (f.getType() == FieldType.TIMESTAMP) {
for (Object v : values) {
doc.add(new IntField(name, toIndexTime((Timestamp) v), store));

View File

@@ -450,16 +450,15 @@ public class ChangeUtil {
return r.toString();
}
public static Timestamp timeFromSortKey(String sortKey) {
public static long parseSortKey(String sortKey) {
if ("z".equals(sortKey)) {
return new Timestamp(Long.MAX_VALUE);
return Long.MAX_VALUE;
}
String ts = sortKey.substring(0, 8);
int i = 0;
while (i < 8 && ts.charAt(i) == '0')
i++;
long v = Long.parseLong(ts.substring(i), 16) * 60;
return new Timestamp((v + SORT_KEY_EPOCH) * 1000);
return Long.parseLong(ts.substring(i), 16);
}
public static void computeSortKey(final Change c) {

View File

@@ -19,6 +19,7 @@ import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.gerrit.reviewdb.client.PatchSetApproval;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.server.ChangeUtil;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.query.change.ChangeQueryBuilder;
import com.google.gerrit.server.query.change.ChangeStatusPredicate;
@@ -43,7 +44,7 @@ import java.util.Set;
*/
public class ChangeField {
/** Increment whenever making schema changes. */
public static final int SCHEMA_VERSION = 5;
public static final int SCHEMA_VERSION = 6;
/** Legacy change ID. */
public static final FieldDef<ChangeData, Integer> CHANGE_ID =
@@ -111,6 +112,18 @@ public class ChangeField {
}
};
/** Sort key field, duplicates {@link #UPDATED}. */
@Deprecated
public static final FieldDef<ChangeData, Long> SORTKEY =
new FieldDef.Single<ChangeData, Long>(
"sortkey", FieldType.LONG, true) {
@Override
public Long get(ChangeData input, FillArgs args)
throws OrmException {
return ChangeUtil.parseSortKey(input.change(args.db).getSortKey());
}
};
/** List of filenames modified in the current patch set. */
public static final FieldDef<ChangeData, Iterable<String>> FILE =
new FieldDef.Repeatable<ChangeData, String>(

View File

@@ -23,6 +23,10 @@ public class FieldType<T> {
public static final FieldType<Integer> INTEGER =
new FieldType<Integer>("INTEGER");
/** A single integer-valued field. */
public static final FieldType<Long> LONG =
new FieldType<Long>("LONG");
/** A single date/time-valued field. */
public static final FieldType<Timestamp> TIMESTAMP =
new FieldType<Timestamp>("TIMESTAMP");

View File

@@ -18,18 +18,15 @@ import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.ChangeUtil;
import com.google.gerrit.server.index.ChangeField;
import com.google.gerrit.server.index.TimestampRangePredicate;
import com.google.gerrit.server.index.IndexPredicate;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Provider;
import java.sql.Timestamp;
public abstract class SortKeyPredicate extends
TimestampRangePredicate<ChangeData> {
public abstract class SortKeyPredicate extends IndexPredicate<ChangeData> {
protected final Provider<ReviewDb> dbProvider;
SortKeyPredicate(Provider<ReviewDb> dbProvider, String name, String value) {
super(ChangeField.UPDATED, name, value);
super(ChangeField.SORTKEY, name, value);
this.dbProvider = dbProvider;
}
@@ -38,19 +35,22 @@ public abstract class SortKeyPredicate extends
return 1;
}
public abstract long getMinValue();
public abstract long getMaxValue();
public static class Before extends SortKeyPredicate {
Before(Provider<ReviewDb> dbProvider, String value) {
super(dbProvider, "sortkey_before", value);
}
@Override
public Timestamp getMinTimestamp() {
return new Timestamp(0);
public long getMinValue() {
return 0;
}
@Override
public Timestamp getMaxTimestamp() {
return ChangeUtil.timeFromSortKey(getValue());
public long getMaxValue() {
return ChangeUtil.parseSortKey(getValue());
}
@Override
@@ -66,13 +66,13 @@ public abstract class SortKeyPredicate extends
}
@Override
public Timestamp getMinTimestamp() {
return ChangeUtil.timeFromSortKey(getValue());
public long getMinValue() {
return ChangeUtil.parseSortKey(getValue());
}
@Override
public Timestamp getMaxTimestamp() {
return new Timestamp(Long.MAX_VALUE);
public long getMaxValue() {
return Long.MAX_VALUE;
}
@Override