Skip to content

Commit

Permalink
refactor: optimize the implementation of indexed query engine through…
Browse files Browse the repository at this point in the history
… query index view
  • Loading branch information
guqing committed Jan 23, 2024
1 parent 14580b9 commit e21daea
Show file tree
Hide file tree
Showing 18 changed files with 738 additions and 565 deletions.
47 changes: 47 additions & 0 deletions api/src/main/java/run/halo/app/extension/index/KeyComparator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package run.halo.app.extension.index;

import java.util.Comparator;
import org.springframework.lang.Nullable;

public class KeyComparator implements Comparator<String> {
public static final KeyComparator INSTANCE = new KeyComparator();

@Override
public int compare(@Nullable String a, @Nullable String b) {
if (a == null && b == null) {
return 0;
} else if (a == null) {
// null less than everything
return 1;
} else if (b == null) {
// null less than everything
return -1;
}

int i = 0;
int j = 0;
while (i < a.length() && j < b.length()) {
if (Character.isDigit(a.charAt(i)) && Character.isDigit(b.charAt(j))) {
// handle number part
int num1 = 0;
int num2 = 0;
while (i < a.length() && Character.isDigit(a.charAt(i))) {
num1 = num1 * 10 + (a.charAt(i++) - '0');
}
while (j < b.length() && Character.isDigit(b.charAt(j))) {
num2 = num2 * 10 + (b.charAt(j++) - '0');
}
if (num1 != num2) {
return num1 - num2;
}
} else if (a.charAt(i) != b.charAt(j)) {
// handle non-number part
return a.charAt(i) - b.charAt(j);
} else {
i++;
j++;
}
}
return a.length() - b.length();
}
}
2 changes: 2 additions & 0 deletions api/src/main/java/run/halo/app/extension/index/query/And.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ public NavigableSet<String> matches(QueryIndexView indexView) {
NavigableSet<String> resultSet = null;
for (Query query : childQueries) {
NavigableSet<String> currentResult = query.matches(indexView);
// Trim unneeded rows to shrink the dataset for the next query
indexView.removeByIdNotIn(currentResult);
if (resultSet == null) {
resultSet = Sets.newTreeSet(currentResult);
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package run.halo.app.extension.index.query;

import java.util.NavigableSet;
import org.springframework.util.Assert;

public class EqualQuery extends SimpleQuery {

Expand All @@ -10,6 +11,7 @@ public EqualQuery(String fieldName, String value) {

public EqualQuery(String fieldName, String value, boolean isFieldRef) {
super(fieldName, value, isFieldRef);
Assert.notNull(value, "Value must not be null, use IsNull or IsNotNull instead");
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package run.halo.app.extension.index.query;

import java.util.NavigableSet;

public class IsNotNull extends SimpleQuery {

protected IsNotNull(String fieldName) {
super(fieldName, null);
}

@Override
public NavigableSet<String> matches(QueryIndexView indexView) {
return indexView.getAllIdsForField(fieldName);
}
}
18 changes: 18 additions & 0 deletions api/src/main/java/run/halo/app/extension/index/query/IsNull.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package run.halo.app.extension.index.query;

import java.util.NavigableSet;

public class IsNull extends SimpleQuery {

protected IsNull(String fieldName) {
super(fieldName, null);
}

@Override
public NavigableSet<String> matches(QueryIndexView indexView) {
var allIds = indexView.getAllIds();
var idsForField = indexView.getAllIdsForField(fieldName);
allIds.removeAll(idsForField);
return allIds;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.google.common.collect.Sets;
import java.util.NavigableSet;
import org.springframework.util.Assert;

public class NotEqual extends SimpleQuery {
private final EqualQuery equalQuery;
Expand All @@ -12,6 +13,7 @@ public NotEqual(String fieldName, String value) {

public NotEqual(String fieldName, String value, boolean isFieldRef) {
super(fieldName, value, isFieldRef);
Assert.notNull(value, "Value must not be null, use IsNull or IsNotNull instead");
this.equalQuery = new EqualQuery(fieldName, value, isFieldRef);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,35 @@ public static Query all(String fieldName) {
return new All(fieldName);
}

public static Query isNull(String fieldName) {
return new IsNull(fieldName);
}

public static Query isNotNull(String fieldName) {
return new IsNotNull(fieldName);
}

/**
* Create a {@link NotEqual} for the given {@code fieldName} and {@code attributeValue}.
*/
public static Query notEqual(String fieldName, String attributeValue) {
if (attributeValue == null) {
return new IsNotNull(fieldName);
}
return new NotEqual(fieldName, attributeValue);
}

public static Query notEqualOtherField(String fieldName, String otherFieldName) {
return new NotEqual(fieldName, otherFieldName, true);
}

/**
* Create a {@link EqualQuery} for the given {@code fieldName} and {@code attributeValue}.
*/
public static Query equal(String fieldName, String attributeValue) {
if (attributeValue == null) {
return new IsNull(fieldName);
}
return new EqualQuery(fieldName, attributeValue);
}

Expand Down Expand Up @@ -73,6 +93,9 @@ public static Query in(String fieldName, String... attributeValues) {
return in(fieldName, Set.of(attributeValues));
}

/**
* Create an {@link InQuery} for the given {@code fieldName} and {@code values}.
*/
public static Query in(String fieldName, Collection<String> values) {
Assert.notNull(values, "Values must not be null");
if (values.size() == 1) {
Expand All @@ -85,6 +108,9 @@ public static Query in(String fieldName, Collection<String> values) {
return new InQuery(fieldName, valueSet);
}

/**
* Create an {@link And} for the given {@link Query}s.
*/
public static Query and(Collection<Query> queries) {
Assert.notEmpty(queries, "Queries must not be empty");
if (queries.size() == 1) {
Expand All @@ -98,6 +124,9 @@ public static And and(Query query1, Query query2) {
return new And(queries);
}

/**
* Create an {@link And} for the given {@link Query}s.
*/
public static Query and(Query query1, Query query2, Query... additionalQueries) {
var queries = new ArrayList<Query>(2 + additionalQueries.length);
queries.add(query1);
Expand All @@ -106,6 +135,9 @@ public static Query and(Query query1, Query query2, Query... additionalQueries)
return new And(queries);
}

/**
* Create an {@link And} for the given {@link Query}s.
*/
public static Query and(Query query1, Query query2, Collection<Query> additionalQueries) {
var queries = new ArrayList<Query>(2 + additionalQueries.size());
queries.add(query1);
Expand All @@ -119,6 +151,9 @@ public static Query or(Query query1, Query query2) {
return new Or(queries);
}

/**
* Create an {@link Or} for the given {@link Query}s.
*/
public static Query or(Query query1, Query query2, Query... additionalQueries) {
var queries = new ArrayList<Query>(2 + additionalQueries.length);
queries.add(query1);
Expand All @@ -127,6 +162,9 @@ public static Query or(Query query1, Query query2, Query... additionalQueries) {
return new Or(queries);
}

/**
* Create an {@link Or} for the given {@link Query}s.
*/
public static Query or(Query query1, Query query2, Collection<Query> additionalQueries) {
var queries = new ArrayList<Query>(2 + additionalQueries.size());
queries.add(query1);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package run.halo.app.extension.index.query;

import java.util.List;
import java.util.NavigableSet;
import org.springframework.data.domain.Sort;
import run.halo.app.extension.Metadata;
import run.halo.app.extension.index.IndexSpec;

Expand Down Expand Up @@ -37,14 +39,21 @@ public interface QueryIndexView {
NavigableSet<String> getAllValuesForField(String fieldName);

/**
* Gets all object ids for a given field name.
* Gets all object ids for a given field name without null cells.
*
* @param fieldName the field name
* @return all indexed object ids for the given field name
* @throws IllegalArgumentException if the field name is not indexed
*/
NavigableSet<String> getAllIdsForField(String fieldName);

/**
* Gets all object ids in this view.
*
* @return all object ids in this view
*/
NavigableSet<String> getAllIds();

NavigableSet<String> findIdsForFieldValueEqual(String fieldName1, String fieldName2);

NavigableSet<String> findIdsForFieldValueGreaterThan(String fieldName1, String fieldName2,
Expand All @@ -53,5 +62,7 @@ NavigableSet<String> findIdsForFieldValueGreaterThan(String fieldName1, String f
NavigableSet<String> findIdsForFieldValueLessThan(String fieldName1, String fieldName2,
boolean orEqual);

void removeAllFieldValuesByIdNotIn(NavigableSet<String> ids);
void removeByIdNotIn(NavigableSet<String> ids);

List<String> sortBy(Sort sort);
}

0 comments on commit e21daea

Please sign in to comment.