Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: only select the required index fields when build query index view #5312

Merged
merged 1 commit into from
Feb 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

import java.util.Collection;
import java.util.Objects;
import lombok.Getter;

@Getter
public abstract class LogicalQuery implements Query {
protected final Collection<Query> childQueries;
protected final int size;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import lombok.experimental.UtilityClass;
import org.springframework.util.Assert;
Expand Down Expand Up @@ -207,4 +208,26 @@ public static Query endsWith(String fieldName, String value) {
public static Query contains(String fieldName, String value) {
return new StringContains(fieldName, value);
}

/**
* Get all the field names used in the given query.
*
* @param query the query
* @return the field names used in the given query
*/
public static List<String> getFieldNamesUsedInQuery(Query query) {
List<String> fieldNames = new ArrayList<>();

if (query instanceof SimpleQuery simpleQuery) {
if (simpleQuery.isFieldRef()) {
fieldNames.add(simpleQuery.getValue());
}
fieldNames.add(simpleQuery.getFieldName());
} else if (query instanceof LogicalQuery logicalQuery) {
for (Query childQuery : logicalQuery.getChildQueries()) {
fieldNames.addAll(getFieldNamesUsedInQuery(childQuery));
}
}
return fieldNames;
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package run.halo.app.extension.index.query;

import lombok.Getter;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.Assert;

@Getter
public abstract class SimpleQuery implements Query {
protected final String fieldName;
protected final String value;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,28 @@

import static org.assertj.core.api.Assertions.assertThat;
import static run.halo.app.extension.index.query.QueryFactory.all;
import static run.halo.app.extension.index.query.QueryFactory.and;
import static run.halo.app.extension.index.query.QueryFactory.between;
import static run.halo.app.extension.index.query.QueryFactory.contains;
import static run.halo.app.extension.index.query.QueryFactory.endsWith;
import static run.halo.app.extension.index.query.QueryFactory.equal;
import static run.halo.app.extension.index.query.QueryFactory.equalOtherField;
import static run.halo.app.extension.index.query.QueryFactory.getFieldNamesUsedInQuery;
import static run.halo.app.extension.index.query.QueryFactory.greaterThan;
import static run.halo.app.extension.index.query.QueryFactory.greaterThanOrEqual;
import static run.halo.app.extension.index.query.QueryFactory.greaterThanOrEqualOtherField;
import static run.halo.app.extension.index.query.QueryFactory.greaterThanOtherField;
import static run.halo.app.extension.index.query.QueryFactory.in;
import static run.halo.app.extension.index.query.QueryFactory.isNotNull;
import static run.halo.app.extension.index.query.QueryFactory.isNull;
import static run.halo.app.extension.index.query.QueryFactory.lessThan;
import static run.halo.app.extension.index.query.QueryFactory.lessThanOrEqual;
import static run.halo.app.extension.index.query.QueryFactory.lessThanOrEqualOtherField;
import static run.halo.app.extension.index.query.QueryFactory.lessThanOtherField;
import static run.halo.app.extension.index.query.QueryFactory.notEqual;
import static run.halo.app.extension.index.query.QueryFactory.notEqualOtherField;
import static run.halo.app.extension.index.query.QueryFactory.or;
import static run.halo.app.extension.index.query.QueryFactory.startsWith;

import org.junit.jupiter.api.Test;

Expand All @@ -30,7 +47,7 @@ void allTest() {
@Test
void isNullTest() {
var indexView = IndexViewDataSet.createPostIndexViewWithNullCell();
var resultSet = QueryFactory.isNull("publishTime").matches(indexView);
var resultSet = isNull("publishTime").matches(indexView);
assertThat(resultSet).containsExactlyInAnyOrder(
"102", "103", "104", "108"
);
Expand All @@ -39,7 +56,7 @@ void isNullTest() {
@Test
void isNotNullTest() {
var indexView = IndexViewDataSet.createPostIndexViewWithNullCell();
var resultSet = QueryFactory.isNotNull("publishTime").matches(indexView);
var resultSet = isNotNull("publishTime").matches(indexView);
assertThat(resultSet).containsExactlyInAnyOrder(
"100", "101", "105", "106", "107"
);
Expand Down Expand Up @@ -85,7 +102,7 @@ void notEqualOtherFieldTest() {
@Test
void lessThanTest() {
var indexView = IndexViewDataSet.createEmployeeIndexView();
var resultSet = QueryFactory.lessThan("id", "103").matches(indexView);
var resultSet = lessThan("id", "103").matches(indexView);
assertThat(resultSet).containsExactlyInAnyOrder(
"100", "101", "102"
);
Expand All @@ -94,7 +111,7 @@ void lessThanTest() {
@Test
void lessThanOtherFieldTest() {
var indexView = IndexViewDataSet.createEmployeeIndexView();
var resultSet = QueryFactory.lessThanOtherField("id", "managerId").matches(indexView);
var resultSet = lessThanOtherField("id", "managerId").matches(indexView);
assertThat(resultSet).containsExactlyInAnyOrder(
"100", "101"
);
Expand All @@ -103,7 +120,7 @@ void lessThanOtherFieldTest() {
@Test
void lessThanOrEqualTest() {
var indexView = IndexViewDataSet.createEmployeeIndexView();
var resultSet = QueryFactory.lessThanOrEqual("id", "103").matches(indexView);
var resultSet = lessThanOrEqual("id", "103").matches(indexView);
assertThat(resultSet).containsExactlyInAnyOrder(
"100", "101", "102", "103"
);
Expand All @@ -113,7 +130,7 @@ void lessThanOrEqualTest() {
void lessThanOrEqualOtherFieldTest() {
var indexView = IndexViewDataSet.createEmployeeIndexView();
var resultSet =
QueryFactory.lessThanOrEqualOtherField("id", "managerId").matches(indexView);
lessThanOrEqualOtherField("id", "managerId").matches(indexView);
assertThat(resultSet).containsExactlyInAnyOrder(
"100", "101", "102", "103"
);
Expand All @@ -122,7 +139,7 @@ void lessThanOrEqualOtherFieldTest() {
@Test
void greaterThanTest() {
var indexView = IndexViewDataSet.createEmployeeIndexView();
var resultSet = QueryFactory.greaterThan("id", "103").matches(indexView);
var resultSet = greaterThan("id", "103").matches(indexView);
assertThat(resultSet).containsExactlyInAnyOrder(
"104", "105"
);
Expand All @@ -131,7 +148,7 @@ void greaterThanTest() {
@Test
void greaterThanOtherFieldTest() {
var indexView = IndexViewDataSet.createEmployeeIndexView();
var resultSet = QueryFactory.greaterThanOtherField("id", "managerId").matches(indexView);
var resultSet = greaterThanOtherField("id", "managerId").matches(indexView);
assertThat(resultSet).containsExactlyInAnyOrder(
"104", "105"
);
Expand All @@ -140,7 +157,7 @@ void greaterThanOtherFieldTest() {
@Test
void greaterThanOrEqualTest() {
var indexView = IndexViewDataSet.createEmployeeIndexView();
var resultSet = QueryFactory.greaterThanOrEqual("id", "103").matches(indexView);
var resultSet = greaterThanOrEqual("id", "103").matches(indexView);
assertThat(resultSet).containsExactlyInAnyOrder(
"103", "104", "105"
);
Expand All @@ -150,7 +167,7 @@ void greaterThanOrEqualTest() {
void greaterThanOrEqualOtherFieldTest() {
var indexView = IndexViewDataSet.createEmployeeIndexView();
var resultSet =
QueryFactory.greaterThanOrEqualOtherField("id", "managerId").matches(indexView);
greaterThanOrEqualOtherField("id", "managerId").matches(indexView);
assertThat(resultSet).containsExactlyInAnyOrder(
"102", "103", "104", "105"
);
Expand All @@ -159,7 +176,7 @@ void greaterThanOrEqualOtherFieldTest() {
@Test
void inTest() {
var indexView = IndexViewDataSet.createEmployeeIndexView();
var resultSet = QueryFactory.in("id", "103", "104").matches(indexView);
var resultSet = in("id", "103", "104").matches(indexView);
assertThat(resultSet).containsExactlyInAnyOrder(
"103", "104"
);
Expand All @@ -168,7 +185,7 @@ void inTest() {
@Test
void inTest2() {
var indexView = IndexViewDataSet.createEmployeeIndexView();
var resultSet = QueryFactory.in("lastName", "Fay").matches(indexView);
var resultSet = in("lastName", "Fay").matches(indexView);
assertThat(resultSet).containsExactlyInAnyOrder(
"100", "104", "105"
);
Expand Down Expand Up @@ -221,7 +238,7 @@ void betweenExclusive() {
@Test
void startsWithTest() {
var indexView = IndexViewDataSet.createEmployeeIndexView();
var resultSet = QueryFactory.startsWith("firstName", "W").matches(indexView);
var resultSet = startsWith("firstName", "W").matches(indexView);
assertThat(resultSet).containsExactlyInAnyOrder(
"102"
);
Expand All @@ -230,7 +247,7 @@ void startsWithTest() {
@Test
void endsWithTest() {
var indexView = IndexViewDataSet.createEmployeeIndexView();
var resultSet = QueryFactory.endsWith("firstName", "y").matches(indexView);
var resultSet = endsWith("firstName", "y").matches(indexView);
assertThat(resultSet).containsExactlyInAnyOrder(
"103"
);
Expand All @@ -239,11 +256,11 @@ void endsWithTest() {
@Test
void containsTest() {
var indexView = IndexViewDataSet.createEmployeeIndexView();
var resultSet = QueryFactory.contains("firstName", "i").matches(indexView);
var resultSet = contains("firstName", "i").matches(indexView);
assertThat(resultSet).containsExactlyInAnyOrder(
"102"
);
resultSet = QueryFactory.contains("firstName", "N").matches(indexView);
resultSet = contains("firstName", "N").matches(indexView);
assertThat(resultSet).containsExactlyInAnyOrder(
"104", "105"
);
Expand All @@ -258,4 +275,33 @@ void notTest() {
"100", "101", "103", "104", "105"
);
}

@Test
void getUsedFieldNamesTest() {
// single query
var query = equal("firstName", "W");
var fieldNames = getFieldNamesUsedInQuery(query);
assertThat(fieldNames).containsExactlyInAnyOrder("firstName");

// and composite query
query = and(
and(equal("firstName", "W"), equal("lastName", "Fay")),
or(equalOtherField("id", "userId"), lessThan("age", "123"))
);
fieldNames = getFieldNamesUsedInQuery(query);
assertThat(fieldNames).containsExactlyInAnyOrder("firstName", "lastName", "id", "userId",
"age");

// or composite query
var complexQuery = or(
equal("field1", "value1"),
and(
equal("field2", "value2"),
equal("field3", "value3")
),
equal("field4", "value4")
);
fieldNames = getFieldNamesUsedInQuery(complexQuery);
assertThat(fieldNames).containsExactlyInAnyOrder("field1", "field2", "field3", "field4");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.stream.Collectors;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Sort;
Expand All @@ -20,6 +22,7 @@
import run.halo.app.extension.ListOptions;
import run.halo.app.extension.ListResult;
import run.halo.app.extension.PageRequest;
import run.halo.app.extension.index.query.QueryFactory;
import run.halo.app.extension.index.query.QueryIndexViewImpl;
import run.halo.app.extension.router.selector.FieldSelector;
import run.halo.app.extension.router.selector.LabelSelector;
Expand Down Expand Up @@ -145,8 +148,12 @@ List<String> doRetrieve(Indexer indexer, ListOptions options, Sort sort) {
stopWatch.stop();

stopWatch.start("build index view");
var fieldNamesUsedInQuery = getFieldNamesUsedInListOptions(options, sort);
var indexViewMap = new HashMap<String, Collection<Map.Entry<String, String>>>();
for (Map.Entry<String, IndexEntry> entry : fieldPathEntryMap.entrySet()) {
if (!fieldNamesUsedInQuery.contains(entry.getKey())) {
continue;
}
indexViewMap.put(entry.getKey(), entry.getValue().immutableEntries());
}
// TODO optimize build indexView time
Expand Down Expand Up @@ -183,6 +190,22 @@ List<String> doRetrieve(Indexer indexer, ListOptions options, Sort sort) {
return result;
}

@NonNull
private Set<String> getFieldNamesUsedInListOptions(ListOptions options, Sort sort) {
var fieldNamesUsedInQuery = new HashSet<String>();
fieldNamesUsedInQuery.add(PrimaryKeySpecUtils.PRIMARY_INDEX_NAME);
for (Sort.Order order : sort) {
fieldNamesUsedInQuery.add(order.getProperty());
}
var hasFieldSelector = hasFieldSelector(options.getFieldSelector());
if (hasFieldSelector) {
var fieldQuery = options.getFieldSelector().query();
var fieldNames = QueryFactory.getFieldNamesUsedInQuery(fieldQuery);
fieldNamesUsedInQuery.addAll(fieldNames);
}
return fieldNamesUsedInQuery;
}

boolean hasLabelSelector(LabelSelector labelSelector) {
return labelSelector != null && !CollectionUtils.isEmpty(labelSelector.getMatchers());
}
Expand Down