optimize query perf (#1711)

* add OneIdQuery and idsSize() method
* change IdQuery.ids and ConditionQuery.conditions to list type
* JsonVertex.properties() only copy array if needed

Change-Id: I711a9c498c688ce31f6df5973b68027a69b063fa
This commit is contained in:
Jermy Li 2021-12-28 19:21:22 +08:00 committed by GitHub
parent dee538ad34
commit 26413a8327
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 308 additions and 146 deletions

View File

@ -443,16 +443,28 @@ public class VertexAPI extends BatchAPI {
@Override
public Object[] properties() {
Object[] props = API.properties(this.properties);
List<Object> list = new ArrayList<>(Arrays.asList(props));
int newSize = props.length;
int appendIndex = newSize;
if (this.label != null) {
list.add(T.label);
list.add(this.label);
newSize += 2;
}
if (this.id != null) {
list.add(T.id);
list.add(this.id);
newSize += 2;
}
return list.toArray();
if (newSize == props.length) {
return props;
}
Object[] newProps = Arrays.copyOf(props, newSize);
if (this.label != null) {
newProps[appendIndex++] = T.label;
newProps[appendIndex++] = this.label;
}
if (this.id != null) {
newProps[appendIndex++] = T.id;
newProps[appendIndex++] = this.id;
}
return newProps;
}
@Override

View File

@ -186,7 +186,7 @@ public abstract class CassandraTable
// Is query by id?
List<Select> ids = this.queryId2Select(query, select);
if (query.conditions().isEmpty()) {
if (query.conditionsSize() == 0) {
// Query only by id
this.setPageState(query, ids);
LOG.debug("Query only by id(s): {}", ids);
@ -251,13 +251,13 @@ public abstract class CassandraTable
protected List<Select> queryId2Select(Query query, Select select) {
// Query by id(s)
if (query.ids().isEmpty()) {
if (query.idsSize() == 0) {
return ImmutableList.of(select);
}
List<HugeKeys> nameParts = this.idColumnName();
List<List<Object>> ids = new ArrayList<>(query.ids().size());
List<List<Object>> ids = new ArrayList<>(query.idsSize());
for (Id id : query.ids()) {
List<Object> idParts = this.idColumnValue(id);
if (nameParts.size() != idParts.size()) {
@ -304,7 +304,7 @@ public abstract class CassandraTable
protected Collection<Select> queryCondition2Select(Query query,
Select select) {
// Query by conditions
Set<Condition> conditions = query.conditions();
Collection<Condition> conditions = query.conditions();
for (Condition condition : conditions) {
Clause clause = condition2Cql(condition);
select.where(clause);

View File

@ -20,13 +20,13 @@
package com.baidu.hugegraph.backend.query;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import com.baidu.hugegraph.backend.query.Condition.RelationType;
import com.baidu.hugegraph.type.HugeType;
import com.baidu.hugegraph.type.define.HugeKeys;
import com.baidu.hugegraph.util.E;
import com.baidu.hugegraph.util.InsertionOrderUtil;
public class BatchConditionQuery extends ConditionQuery {
@ -43,7 +43,8 @@ public class BatchConditionQuery extends ConditionQuery {
Object value = query.condition(key);
if (this.in == null) {
assert !this.containsRelation(RelationType.IN);
this.resetConditions(new LinkedHashSet<>(query.conditions()));
this.resetConditions(InsertionOrderUtil.newList(
(List<Condition>) query.conditions()));
this.unsetCondition(key);
List<Object> list = new ArrayList<>(this.batchSize);

View File

@ -21,6 +21,7 @@ package com.baidu.hugegraph.backend.query;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
@ -40,13 +41,13 @@ import com.baidu.hugegraph.perf.PerfUtil.Watched;
import com.baidu.hugegraph.structure.HugeElement;
import com.baidu.hugegraph.structure.HugeProperty;
import com.baidu.hugegraph.type.HugeType;
import com.baidu.hugegraph.type.define.CollectionType;
import com.baidu.hugegraph.type.define.HugeKeys;
import com.baidu.hugegraph.util.E;
import com.baidu.hugegraph.util.InsertionOrderUtil;
import com.baidu.hugegraph.util.LongEncoding;
import com.baidu.hugegraph.util.NumericUtil;
import com.baidu.hugegraph.util.collection.CollectionFactory;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
@ -70,10 +71,10 @@ public class ConditionQuery extends IdQuery {
IGNORE_SYM_SET = ImmutableSet.copyOf(list);
}
private static final Set<Condition> EMPTY_CONDITIONS = ImmutableSet.of();
private static final List<Condition> EMPTY_CONDITIONS = ImmutableList.of();
// Conditions will be concated with `and` by default
private Set<Condition> conditions = EMPTY_CONDITIONS;
private List<Condition> conditions = EMPTY_CONDITIONS;
private OptimizedType optimizedType = OptimizedType.NONE;
private Function<HugeElement, Boolean> resultsFilter = null;
@ -101,7 +102,7 @@ public class ConditionQuery extends IdQuery {
}
if (this.conditions == EMPTY_CONDITIONS) {
this.conditions = CollectionFactory.newSet(CollectionType.EC);
this.conditions = InsertionOrderUtil.newList();
}
this.conditions.add(condition);
return this;
@ -152,16 +153,21 @@ public class ConditionQuery extends IdQuery {
}
@Override
public Set<Condition> conditions() {
return Collections.unmodifiableSet(this.conditions);
public int conditionsSize() {
return this.conditions.size();
}
public void resetConditions(Set<Condition> conditions) {
@Override
public Collection<Condition> conditions() {
return Collections.unmodifiableList(this.conditions);
}
public void resetConditions(List<Condition> conditions) {
this.conditions = conditions;
}
public void resetConditions() {
this.conditions = new LinkedHashSet<>();
this.conditions = EMPTY_CONDITIONS;
}
public void recordIndexValue(Id propertyId, Id id, Object indexValue) {
@ -475,11 +481,9 @@ public class ConditionQuery extends IdQuery {
public ConditionQuery copy() {
ConditionQuery query = (ConditionQuery) super.copy();
query.originQuery(this);
query.conditions = this.conditions == EMPTY_CONDITIONS ?
EMPTY_CONDITIONS :
CollectionFactory.newSet(CollectionType.EC,
this.conditions);
if (query.conditions != EMPTY_CONDITIONS) {
query.conditions = InsertionOrderUtil.newList(this.conditions);
}
query.optimizedType = OptimizedType.NONE;
query.resultsFilter = null;
@ -504,7 +508,7 @@ public class ConditionQuery extends IdQuery {
return this.resultsFilter.apply(element);
}
boolean valid = true;
for (Condition cond : this.conditions()) {
for (Condition cond : this.conditions) {
valid &= cond.test(element);
valid &= (this.element2IndexValueMap == null ||
this.element2IndexValueMap.validRangeIndex(element, cond));
@ -528,7 +532,7 @@ public class ConditionQuery extends IdQuery {
public boolean mayHasDupKeys(Set<HugeKeys> keys) {
Map<HugeKeys, Integer> keyCounts = new HashMap<>();
for (Condition condition : this.conditions()) {
for (Condition condition : this.conditions) {
if (!condition.isRelation()) {
// Assume may exist duplicate keys when has nested conditions
return true;

View File

@ -51,13 +51,13 @@ public final class ConditionQueryFlatten {
public static List<ConditionQuery> flatten(ConditionQuery query,
boolean supportIn) {
if (query.isFlattened() && !query.mayHasDupKeys(SPECIAL_KEYS)) {
return Arrays.asList(query);
return ImmutableList.of(query);
}
List<ConditionQuery> queries = new ArrayList<>();
// Flatten IN/NOT_IN if needed
Set<Condition> conditions = InsertionOrderUtil.newSet();
List<Condition> conditions = InsertionOrderUtil.newList();
for (Condition condition : query.conditions()) {
Condition cond = flattenIn(condition, supportIn);
if (cond == null) {

View File

@ -19,8 +19,9 @@
package com.baidu.hugegraph.backend.query;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import com.baidu.hugegraph.backend.id.Id;
@ -28,14 +29,15 @@ import com.baidu.hugegraph.structure.HugeElement;
import com.baidu.hugegraph.type.HugeType;
import com.baidu.hugegraph.util.E;
import com.baidu.hugegraph.util.InsertionOrderUtil;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
public class IdQuery extends Query {
private static final Set<Id> EMPTY_IDS = ImmutableSet.of();
private static final List<Id> EMPTY_IDS = ImmutableList.of();
// The id(s) will be concated with `or`
private Set<Id> ids = EMPTY_IDS;
private List<Id> ids = EMPTY_IDS;
private boolean mustSortByInput = true;
public IdQuery(HugeType resultType) {
@ -75,8 +77,13 @@ public class IdQuery extends Query {
}
@Override
public Set<Id> ids() {
return Collections.unmodifiableSet(this.ids);
public int idsSize() {
return this.ids.size();
}
@Override
public Collection<Id> ids() {
return Collections.unmodifiableList(this.ids);
}
public void resetIds() {
@ -86,8 +93,15 @@ public class IdQuery extends Query {
public IdQuery query(Id id) {
E.checkArgumentNotNull(id, "Query id can't be null");
if (this.ids == EMPTY_IDS) {
this.ids = new LinkedHashSet<>();
this.ids = InsertionOrderUtil.newList();
}
int last = this.ids.size() - 1;
if (last >= 0 && id.equals(this.ids.get(last))) {
// The same id as the previous one, just ignore it
return this;
}
this.ids.add(id);
this.checkCapacity(this.ids.size());
return this;
@ -109,7 +123,70 @@ public class IdQuery extends Query {
public IdQuery copy() {
IdQuery query = (IdQuery) super.copy();
query.ids = this.ids == EMPTY_IDS ? EMPTY_IDS :
InsertionOrderUtil.newSet(this.ids);
InsertionOrderUtil.newList(this.ids);
return query;
}
public static final class OneIdQuery extends IdQuery {
private Id id;
public OneIdQuery(HugeType resultType, Id id) {
super(resultType);
super.mustSortByInput = false;
this.id = id;
}
public OneIdQuery(Query originQuery, Id id) {
super(originQuery.resultType(), originQuery);
super.mustSortByInput = false;
this.id = id;
}
public Id id() {
return this.id;
}
public void resetId(Id id) {
this.id = id;
}
@Override
public int idsSize() {
return this.id == null ? 0 : 1;
}
@Override
public Set<Id> ids() {
return this.id == null ? ImmutableSet.of() :
ImmutableSet.of(this.id);
}
@Override
public void resetIds() {
this.id = null;
}
@Override
public IdQuery query(Id id) {
E.checkArgumentNotNull(id, "Query id can't be null");
this.id = id;
return this;
}
@Override
public boolean test(HugeElement element) {
if (this.id == null) {
return true;
}
return this.id.equals(element.id());
}
@Override
public IdQuery copy() {
OneIdQuery query = (OneIdQuery) super.copy();
assert this.id.equals(query.id);
return query;
}
}
}

View File

@ -19,6 +19,7 @@
package com.baidu.hugegraph.backend.query;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Objects;
@ -36,6 +37,7 @@ import com.baidu.hugegraph.util.CollectionUtil;
import com.baidu.hugegraph.util.E;
import com.baidu.hugegraph.util.InsertionOrderUtil;
import com.baidu.hugegraph.util.collection.IdSet;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
public class Query implements Cloneable {
@ -442,16 +444,24 @@ public class Query implements Cloneable {
this.showExpired = showExpired;
}
public Set<Id> ids() {
return ImmutableSet.of();
public Collection<Id> ids() {
return ImmutableList.of();
}
public Set<Condition> conditions() {
return ImmutableSet.of();
public Collection<Condition> conditions() {
return ImmutableList.of();
}
public int idsSize() {
return 0;
}
public int conditionsSize() {
return 0;
}
public boolean empty() {
return this.ids().isEmpty() && this.conditions().isEmpty();
return this.idsSize() == 0 && this.conditionsSize() == 0;
}
public boolean test(HugeElement element) {

View File

@ -19,6 +19,7 @@
package com.baidu.hugegraph.backend.query;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
@ -36,6 +37,7 @@ import com.baidu.hugegraph.iterator.CIter;
import com.baidu.hugegraph.iterator.FlatMapperIterator;
import com.baidu.hugegraph.iterator.ListIterator;
import com.baidu.hugegraph.iterator.MapperIterator;
import com.baidu.hugegraph.perf.PerfUtil.Watched;
import com.baidu.hugegraph.type.Idfiable;
import com.baidu.hugegraph.util.E;
import com.baidu.hugegraph.util.InsertionOrderUtil;
@ -103,7 +105,7 @@ public class QueryResults<R> {
// None result found
return origin;
}
Set<Id> ids;
Collection<Id> ids;
if (!this.mustSortByInputIds() || this.paging() ||
(ids = this.queryIds()).size() <= 1) {
/*
@ -168,7 +170,7 @@ public class QueryResults<R> {
return false;
}
private Set<Id> queryIds() {
private Collection<Id> queryIds() {
assert !this.queries.isEmpty();
if (this.queries.size() == 1) {
return this.queries.get(0).ids();
@ -181,6 +183,7 @@ public class QueryResults<R> {
return ids;
}
@Watched
public static <T> ListIterator<T> toList(Iterator<T> iterator) {
try {
return new ListIterator<>(Query.DEFAULT_CAPACITY, iterator);
@ -189,6 +192,7 @@ public class QueryResults<R> {
}
}
@Watched
public static <T> void fillList(Iterator<T> iterator, List<T> list) {
try {
while (iterator.hasNext()) {
@ -201,6 +205,7 @@ public class QueryResults<R> {
}
}
@Watched
public static <T extends Idfiable> void fillMap(Iterator<T> iterator,
Map<Id, T> map) {
try {
@ -234,6 +239,7 @@ public class QueryResults<R> {
return qr[0];
}
@Watched
public static <T> T one(Iterator<T> iterator) {
try {
if (iterator.hasNext()) {
@ -251,9 +257,13 @@ public class QueryResults<R> {
return null;
}
public static <T> Iterator<T> iterator(T elem) {
return new OneIterator<>(elem);
}
@SuppressWarnings("unchecked")
public static <R> QueryResults<R> empty() {
return (QueryResults<R>) EMPTY;
public static <T> QueryResults<T> empty() {
return (QueryResults<T>) EMPTY;
}
@SuppressWarnings("unchecked")
@ -285,4 +295,39 @@ public class QueryResults<R> {
// pass
}
}
private static class OneIterator<T> implements CIter<T> {
private T element;
public OneIterator(T element) {
assert element != null;
this.element = element;
}
@Override
public Object metadata(String meta, Object... args) {
return null;
}
@Override
public boolean hasNext() {
return this.element != null;
}
@Override
public T next() {
if (this.element == null) {
throw new NoSuchElementException();
}
T result = this.element;
this.element = null;
return result;
}
@Override
public void close() throws Exception {
// pass
}
}
}

View File

@ -47,8 +47,8 @@ public abstract class AbstractSerializer
HugeType type = query.resultType();
// Serialize edge condition query (TODO: add VEQ(for EOUT/EIN))
if (type.isEdge() && !query.conditions().isEmpty()) {
if (!query.ids().isEmpty()) {
if (type.isEdge() && query.conditionsSize() > 0) {
if (query.idsSize() > 0) {
throw new BackendException("Not supported query edge by id " +
"and by condition at the same time");
}
@ -60,7 +60,11 @@ public abstract class AbstractSerializer
}
// Serialize id in query
if (query instanceof IdQuery && !query.ids().isEmpty()) {
if (query.idsSize() == 1 && query instanceof IdQuery.OneIdQuery) {
IdQuery.OneIdQuery result = (IdQuery.OneIdQuery) query.copy();
result.resetId(this.writeQueryId(type, result.id()));
query = result;
} else if (query.idsSize() > 0 && query instanceof IdQuery) {
IdQuery result = (IdQuery) query.copy();
result.resetIds();
for (Id id : query.ids()) {
@ -70,7 +74,7 @@ public abstract class AbstractSerializer
}
// Serialize condition(key/value) in query
if (query instanceof ConditionQuery && !query.conditions().isEmpty()) {
if (query instanceof ConditionQuery && query.conditionsSize() > 0) {
query = this.writeQueryCondition(query);
}

View File

@ -671,7 +671,7 @@ public class BinarySerializer extends AbstractSerializer {
}
if (count > 0) {
assert count == cq.conditions().size();
assert count == cq.conditionsSize();
return prefixQuery(cq, new BinaryId(buffer.bytes(), null));
}
@ -700,7 +700,7 @@ public class BinarySerializer extends AbstractSerializer {
private Query writeStringIndexQuery(ConditionQuery query) {
E.checkArgument(query.allSysprop() &&
query.conditions().size() == 2,
query.conditionsSize() == 2,
"There should be two conditions: " +
"INDEX_LABEL_ID and FIELD_VALUES" +
"in secondary index query");

View File

@ -56,9 +56,9 @@ import com.baidu.hugegraph.type.define.Frequency;
import com.baidu.hugegraph.type.define.HugeKeys;
import com.baidu.hugegraph.type.define.IdStrategy;
import com.baidu.hugegraph.type.define.IndexType;
import com.baidu.hugegraph.type.define.WriteType;
import com.baidu.hugegraph.type.define.SchemaStatus;
import com.baidu.hugegraph.type.define.SerialEnum;
import com.baidu.hugegraph.type.define.WriteType;
import com.baidu.hugegraph.util.E;
import com.baidu.hugegraph.util.JsonUtil;
@ -364,7 +364,7 @@ public abstract class TableSerializer extends AbstractSerializer {
@Override
protected Query writeQueryEdgeCondition(Query query) {
query = this.writeQueryCondition(query);
return query.ids().isEmpty() ? query : null;
return query.idsSize() == 0 ? query : null;
}
@Override

View File

@ -447,7 +447,7 @@ public class TextSerializer extends AbstractSerializer {
}
Object label = cq.condition(HugeKeys.LABEL);
List<String> start = new ArrayList<>(cq.conditions().size());
List<String> start = new ArrayList<>(cq.conditionsSize());
start.add(writeEntryId((Id) vertex));
start.add(writeType(((Directions) direction).type()));
start.add(writeId((Id) label));
@ -476,7 +476,7 @@ public class TextSerializer extends AbstractSerializer {
private Query writeQueryEdgePrefixCondition(ConditionQuery cq) {
// Convert query-by-condition to query-by-id
List<String> condParts = new ArrayList<>(cq.conditions().size());
List<String> condParts = new ArrayList<>(cq.conditionsSize());
for (HugeKeys key : EdgeId.KEYS) {
Object value = cq.condition(key);

View File

@ -88,8 +88,7 @@ public abstract class BackendTable<Session extends BackendSession, Entry> {
query = query.originQuery();
}
if (!query.conditions().isEmpty() &&
query instanceof ConditionQuery) {
if (query.conditionsSize() > 0 && query instanceof ConditionQuery) {
ConditionQuery cq = (ConditionQuery) query;
// Does query IN edges
if (cq.condition(HugeKeys.DIRECTION) == Directions.IN) {

View File

@ -20,11 +20,11 @@
package com.baidu.hugegraph.backend.store.memory;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.slf4j.Logger;
@ -171,12 +171,12 @@ public class InMemoryDBTable extends BackendTable<BackendSession,
}
// Query by id(s)
if (!query.ids().isEmpty()) {
if (query.idsSize() > 0) {
rs = this.queryById(query.ids(), rs);
}
// Query by condition(s)
if (!query.conditions().isEmpty()) {
if (query.conditionsSize() > 0) {
ConditionQuery condQuery = (ConditionQuery) query;
if (condQuery.containsScanRelation()) {
return this.queryByRange(condQuery);
@ -225,7 +225,7 @@ public class InMemoryDBTable extends BackendTable<BackendSession,
return rs.iterator();
}
protected Map<Id, BackendEntry> queryById(Set<Id> ids,
protected Map<Id, BackendEntry> queryById(Collection<Id> ids,
Map<Id, BackendEntry> entries) {
assert ids.size() > 0;
Map<Id, BackendEntry> rs = InsertionOrderUtil.newMap();
@ -255,7 +255,7 @@ public class InMemoryDBTable extends BackendTable<BackendSession,
}
protected Map<Id, BackendEntry> queryByFilter(
Set<Condition> conditions,
Collection<Condition> conditions,
Map<Id, BackendEntry> entries) {
assert conditions.size() > 0;

View File

@ -21,13 +21,13 @@ package com.baidu.hugegraph.backend.store.memory;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.NavigableMap;
import java.util.Set;
import java.util.SortedMap;
import java.util.concurrent.ConcurrentSkipListMap;
@ -105,7 +105,7 @@ public class InMemoryDBTables {
@Override
protected Map<Id, BackendEntry> queryById(
Set<Id> ids,
Collection<Id> ids,
Map<Id, BackendEntry> entries) {
// Query edge(in a vertex) by id
return this.queryEdgeById(ids, false, entries);
@ -180,7 +180,7 @@ public class InMemoryDBTables {
}
private Map<Id, BackendEntry> queryEdgeById(
Set<Id> ids, boolean prefix,
Collection<Id> ids, boolean prefix,
Map<Id, BackendEntry> entries) {
assert ids.size() > 0;
Map<Id, BackendEntry> rs = InsertionOrderUtil.newMap();
@ -231,7 +231,7 @@ public class InMemoryDBTables {
@Override
protected Map<Id, BackendEntry> queryByFilter(
Set<Condition> conditions,
Collection<Condition> conditions,
Map<Id, BackendEntry> entries) {
if (conditions.isEmpty()) {
return entries;
@ -368,7 +368,7 @@ public class InMemoryDBTables {
@Override
public Iterator<BackendEntry> query(BackendSession session,
Query query) {
Set<Condition> conditions = query.conditions();
Collection<Condition> conditions = query.conditions();
E.checkState(query instanceof ConditionQuery &&
conditions.size() == 2,
"Secondary index query must be condition query " +
@ -445,7 +445,7 @@ public class InMemoryDBTables {
@Override
public Iterator<BackendEntry> query(BackendSession session,
Query query) {
Set<Condition> conditions = query.conditions();
Collection<Condition> conditions = query.conditions();
E.checkState(query instanceof ConditionQuery &&
(conditions.size() == 3 || conditions.size() == 2),
"Range index query must be condition query" +

View File

@ -269,7 +269,7 @@ public final class RamTable {
ConditionQuery cq = (ConditionQuery) query;
int conditionsSize = cq.conditions().size();
int conditionsSize = cq.conditionsSize();
Object owner = cq.condition(HugeKeys.OWNER_VERTEX);
Directions direction = cq.condition(HugeKeys.DIRECTION);
Id label = cq.condition(HugeKeys.LABEL);
@ -294,7 +294,7 @@ public final class RamTable {
if (label != null) {
matchedConds++;
}
return matchedConds == cq.conditions().size();
return matchedConds == cq.conditionsSize();
}
@Watched

View File

@ -186,7 +186,7 @@ public abstract class AbstractTransaction implements Transaction {
@Watched(prefix = "tx")
public BackendEntry query(HugeType type, Id id) {
IdQuery idQuery = new IdQuery(type, id);
IdQuery idQuery = new IdQuery.OneIdQuery(type, id);
return this.query(idQuery).one();
}

View File

@ -565,7 +565,7 @@ public class GraphTransaction extends IndexableTransaction {
if (this.optimizeAggrByIndex &&
optimized == OptimizedType.INDEX) {
// The ids size means results count (assume no left index)
result = q.ids().size();
result = q.idsSize();
} else {
assert optimized == OptimizedType.INDEX_FILTER ||
optimized == OptimizedType.INDEX;
@ -906,7 +906,7 @@ public class GraphTransaction extends IndexableTransaction {
if (!query.empty()) {
// Query from backend store
if (edges.isEmpty() && query.ids().size() == ids.size()) {
if (edges.isEmpty() && query.idsSize() == ids.size()) {
/*
* Sort at the lower layer and return directly if there is no
* local vertex and duplicated id.
@ -987,7 +987,7 @@ public class GraphTransaction extends IndexableTransaction {
if (vertex == null) {
return null;
}
if (query.ids().size() == 1) {
if (query.idsSize() == 1) {
assert vertex.getEdges().size() == 1;
}
/*
@ -1251,7 +1251,7 @@ public class GraphTransaction extends IndexableTransaction {
private static void verifyVerticesConditionQuery(ConditionQuery query) {
assert query.resultType().isVertex();
int total = query.conditions().size();
int total = query.conditionsSize();
if (total == 1) {
/*
* Supported query:
@ -1283,7 +1283,7 @@ public class GraphTransaction extends IndexableTransaction {
private static void verifyEdgesConditionQuery(ConditionQuery query) {
assert query.resultType().isEdge();
int total = query.conditions().size();
int total = query.conditionsSize();
if (total == 1) {
/*
* Supported query:
@ -1345,7 +1345,7 @@ public class GraphTransaction extends IndexableTransaction {
}
private Query optimizeQuery(ConditionQuery query) {
if (!query.ids().isEmpty()) {
if (query.idsSize() > 0) {
throw new HugeException(
"Not supported querying by id and conditions: %s", query);
}
@ -1418,7 +1418,7 @@ public class GraphTransaction extends IndexableTransaction {
* 1.not query by label
* 2.or query by label and store supports this feature
*/
boolean byLabel = (label != null && query.conditions().size() == 1);
boolean byLabel = (label != null && query.conditionsSize() == 1);
if (!byLabel || this.store().features().supportsQueryByLabel()) {
return query;
}

View File

@ -72,7 +72,7 @@ public class SchemaIndexTransaction extends AbstractTransaction {
public QueryResults<BackendEntry> query(Query query) {
if (query instanceof ConditionQuery) {
ConditionQuery q = (ConditionQuery) query;
if (q.allSysprop() && q.conditions().size() == 1 &&
if (q.allSysprop() && q.conditionsSize() == 1 &&
q.containsCondition(HugeKeys.NAME)) {
return this.queryByName(q);
}
@ -102,7 +102,7 @@ public class SchemaIndexTransaction extends AbstractTransaction {
HugeIndex index = this.serializer.readIndex(graph(), indexQuery,
entries.next());
idQuery.query(index.elementIds());
Query.checkForceCapacity(idQuery.ids().size());
Query.checkForceCapacity(idQuery.idsSize());
}
} finally {
CloseableIterator.closeIterator(entries);
@ -112,8 +112,8 @@ public class SchemaIndexTransaction extends AbstractTransaction {
return QueryResults.empty();
}
assert idQuery.ids().size() == 1 : idQuery.ids();
if (idQuery.ids().size() > 1) {
assert idQuery.idsSize() == 1 : idQuery.ids();
if (idQuery.idsSize() > 1) {
LOG.warn("Multiple ids are found with same name '{}': {}",
name, idQuery.ids());
}

View File

@ -159,7 +159,7 @@ public class HugeVertexStep<E extends Element>
}
// Query by has(id)
if (!query.ids().isEmpty()) {
if (query.idsSize() > 0) {
// Ignore conditions if query by edge id in has-containers
// FIXME: should check that the edge id matches the `vertex`
query.resetConditions();

View File

@ -21,6 +21,7 @@ package com.baidu.hugegraph.backend.store.hbase;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
@ -181,9 +182,9 @@ public class HbaseTable extends BackendTable<Session, BackendEntry> {
}
// Query by id
if (query.conditions().isEmpty()) {
assert !query.ids().isEmpty();
if (query.ids().size() == 1) {
if (query.conditionsSize() == 0) {
assert query.idsSize() > 0;
if (query.idsSize() == 1) {
Id id = query.ids().iterator().next();
return this.queryById(session, id);
} else {
@ -210,7 +211,7 @@ public class HbaseTable extends BackendTable<Session, BackendEntry> {
return session.get(this.table(), null, id.asBytes());
}
protected <R> R queryByIds(HbaseSession<R> session, Set<Id> ids) {
protected <R> R queryByIds(HbaseSession<R> session, Collection<Id> ids) {
Set<byte[]> rowkeys = InsertionOrderUtil.newSet();
for (Id id : ids) {
rowkeys.add(id.asBytes());

View File

@ -23,10 +23,10 @@ import java.math.BigDecimal;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.BiFunction;
import org.apache.logging.log4j.util.Strings;
@ -397,7 +397,7 @@ public abstract class MysqlTable
List<StringBuilder> selections;
if (query.conditions().isEmpty()) {
if (query.conditionsSize() == 0) {
// Query only by id
LOG.debug("Query only by id(s): {}", ids);
selections = ids;
@ -489,13 +489,13 @@ public abstract class MysqlTable
protected List<StringBuilder> queryId2Select(Query query,
StringBuilder select) {
// Query by id(s)
if (query.ids().isEmpty()) {
if (query.idsSize() == 0) {
return ImmutableList.of(select);
}
List<HugeKeys> nameParts = this.idColumnName();
List<List<Object>> ids = new ArrayList<>(query.ids().size());
List<List<Object>> ids = new ArrayList<>(query.idsSize());
for (Id id : query.ids()) {
List<Object> idParts = this.idColumnValue(id);
if (nameParts.size() != idParts.size()) {
@ -547,7 +547,7 @@ public abstract class MysqlTable
protected List<StringBuilder> queryCondition2Select(Query query,
StringBuilder select) {
// Query by conditions
Set<Condition> conditions = query.conditions();
Collection<Condition> conditions = query.conditions();
List<StringBuilder> clauses = new ArrayList<>(conditions.size());
for (Condition condition : conditions) {
clauses.add(this.condition2Sql(condition));
@ -635,7 +635,7 @@ public abstract class MysqlTable
}
// Need add `where` to `select` when query is IdQuery
boolean expectWhere = scan || query.conditions().isEmpty();
boolean expectWhere = scan || query.conditionsSize() == 0;
WhereBuilder where = this.newWhereBuilder(expectWhere);
if (!expectWhere) {
where.and();

View File

@ -20,6 +20,7 @@
package com.baidu.hugegraph.backend.store.rocksdb;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
@ -166,8 +167,8 @@ public class RocksDBTable extends BackendTable<Session, BackendEntry> {
}
// Query by id
if (query.conditions().isEmpty()) {
assert !query.ids().isEmpty();
if (query.conditionsSize() == 0) {
assert query.idsSize() > 0;
return this.queryByIds(session, query.ids());
}
@ -191,7 +192,8 @@ public class RocksDBTable extends BackendTable<Session, BackendEntry> {
return session.scan(this.table(), id.asBytes());
}
protected BackendColumnIterator queryByIds(Session session, Set<Id> ids) {
protected BackendColumnIterator queryByIds(Session session,
Collection<Id> ids) {
if (ids.size() == 1) {
return this.queryById(session, ids.iterator().next());
}
@ -290,6 +292,8 @@ public class RocksDBTable extends BackendTable<Session, BackendEntry> {
HugeType type = query.resultType();
// NOTE: only support BinaryBackendEntry currently
entry = new BinaryBackendEntry(type, col.name);
} else {
assert !Bytes.equals(entry.id().asBytes(), col.name);
}
entry.columns(col);
return entry;

View File

@ -21,8 +21,8 @@ package com.baidu.hugegraph.backend.store.rocksdb;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import com.baidu.hugegraph.backend.id.Id;
import com.baidu.hugegraph.backend.query.Condition;
@ -154,7 +154,7 @@ public class RocksDBTables {
@Override
protected BackendColumnIterator queryByIds(Session session,
Set<Id> ids) {
Collection<Id> ids) {
// TODO: use getByIds() after batch version multi-get is ready
return super.queryByIds(session, ids);
}
@ -262,7 +262,7 @@ public class RocksDBTables {
@Override
protected BackendColumnIterator queryByCond(Session session,
ConditionQuery query) {
assert !query.conditions().isEmpty();
assert query.conditionsSize() > 0;
List<Condition> conds = query.syspropConditions(HugeKeys.ID);
E.checkArgument(!conds.isEmpty(),

View File

@ -19,8 +19,8 @@
package com.baidu.hugegraph.backend.store.scylladb;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import com.baidu.hugegraph.backend.query.Condition;
@ -36,7 +36,7 @@ import com.datastax.driver.core.querybuilder.Select;
public class ScyllaDBTablesWithMV {
private static boolean isQueryBySpecifiedKey(Query query, HugeKeys key) {
Set<Condition> conditions = query.conditions();
Collection<Condition> conditions = query.conditions();
if (query instanceof ConditionQuery && !conditions.isEmpty()) {
ConditionQuery cq = (ConditionQuery) query;
Object value = cq.condition(key);

View File

@ -170,6 +170,12 @@ public class AuthTest extends BaseCoreTest {
Assert.assertEquals("james", users.get(1).name());
Assert.assertEquals("james", users.get(2).name());
users = authManager.listUsers(ImmutableList.of(id1, id2, id1));
Assert.assertEquals(3, users.size());
Assert.assertEquals("tom", users.get(0).name());
Assert.assertEquals("james", users.get(1).name());
Assert.assertEquals("tom", users.get(2).name());
users = authManager.listUsers(ImmutableList.of(id1, id2,
IdGenerator.of("fake")));
Assert.assertEquals(2, users.size());

View File

@ -19,9 +19,9 @@
package com.baidu.hugegraph.unit.core;
import java.util.HashSet;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import org.junit.After;
import org.junit.Test;
@ -35,7 +35,6 @@ import com.baidu.hugegraph.testutil.Assert;
import com.baidu.hugegraph.type.HugeType;
import com.baidu.hugegraph.unit.BaseUnitTest;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
public class ConditionQueryFlattenTest extends BaseUnitTest {
@ -54,9 +53,9 @@ public class ConditionQueryFlattenTest extends BaseUnitTest {
Assert.assertEquals(1, query.conditions().size());
List<ConditionQuery> queries = ConditionQueryFlatten.flatten(query);
Assert.assertEquals(1, queries.size());
Set<Set<Condition>> expect;
expect = ImmutableSet.of(ImmutableSet.of(c1, c2));
Set<Set<Condition>> actual = new HashSet<>();
List<Collection<Condition>> expect;
expect = ImmutableList.of(ImmutableList.of(c1, c2));
List<Collection<Condition>> actual = new ArrayList<>();
for (ConditionQuery q : queries) {
actual.add(q.conditions());
}
@ -77,11 +76,11 @@ public class ConditionQueryFlattenTest extends BaseUnitTest {
query.query(c4);
Assert.assertEquals(4, query.conditions().size());
List<ConditionQuery> queries =
ConditionQueryFlatten.flatten(query);
ConditionQueryFlatten.flatten(query);
Assert.assertEquals(1, queries.size());
Set<Set<Condition>> expect;
expect = ImmutableSet.of(ImmutableSet.of(c1, c2, c3, c4));
Set<Set<Condition>> actual = new HashSet<>();
List<Collection<Condition>> expect;
expect = ImmutableList.of(ImmutableList.of(c1, c2, c3, c4));
List<Collection<Condition>> actual = new ArrayList<>();
for (ConditionQuery q : queries) {
actual.add(q.conditions());
}
@ -100,9 +99,9 @@ public class ConditionQueryFlattenTest extends BaseUnitTest {
Assert.assertEquals(1, query.conditions().size());
List<ConditionQuery> queries = ConditionQueryFlatten.flatten(query);
Assert.assertEquals(1, queries.size());
Set<Set<Condition>> expect;
expect = ImmutableSet.of(ImmutableSet.of(c1, c2, c3, c4));
Set<Set<Condition>> actual = new HashSet<>();
List<Collection<Condition>> expect;
expect = ImmutableList.of(ImmutableList.of(c1, c2, c3, c4));
List<Collection<Condition>> actual = new ArrayList<>();
for (ConditionQuery q : queries) {
actual.add(q.conditions());
}
@ -119,9 +118,9 @@ public class ConditionQueryFlattenTest extends BaseUnitTest {
Assert.assertEquals(1, query.conditions().size());
List<ConditionQuery> queries = ConditionQueryFlatten.flatten(query);
Assert.assertEquals(2, queries.size());
Set<Set<Condition>> expect;
expect = ImmutableSet.of(ImmutableSet.of(c1), ImmutableSet.of(c2));
Set<Set<Condition>> actual = new HashSet<>();
List<Collection<Condition>> expect;
expect = ImmutableList.of(ImmutableList.of(c1), ImmutableList.of(c2));
List<Collection<Condition>> actual = new ArrayList<>();
for (ConditionQuery q : queries) {
actual.add(q.conditions());
}
@ -141,12 +140,12 @@ public class ConditionQueryFlattenTest extends BaseUnitTest {
Assert.assertEquals(2, query.conditions().size());
List<ConditionQuery> queries = ConditionQueryFlatten.flatten(query);
Assert.assertEquals(4, queries.size());
Set<Set<Condition>> expect;
expect = ImmutableSet.of(ImmutableSet.of(c1, c3),
ImmutableSet.of(c1, c4),
ImmutableSet.of(c2, c3),
ImmutableSet.of(c2, c4));
Set<Set<Condition>> actual = new HashSet<>();
List<Collection<Condition>> expect;
expect = ImmutableList.of(ImmutableList.of(c1, c3),
ImmutableList.of(c1, c4),
ImmutableList.of(c2, c3),
ImmutableList.of(c2, c4));
List<Collection<Condition>> actual = new ArrayList<>();
for (ConditionQuery q : queries) {
actual.add(q.conditions());
}
@ -165,10 +164,10 @@ public class ConditionQueryFlattenTest extends BaseUnitTest {
Assert.assertEquals(1, query.conditions().size());
List<ConditionQuery> queries = ConditionQueryFlatten.flatten(query);
Assert.assertEquals(4, queries.size());
Set<Set<Condition>> expect;
expect = ImmutableSet.of(ImmutableSet.of(c1), ImmutableSet.of(c2),
ImmutableSet.of(c3), ImmutableSet.of(c4));
Set<Set<Condition>> actual = new HashSet<>();
List<Collection<Condition>> expect;
expect = ImmutableList.of(ImmutableList.of(c1), ImmutableList.of(c2),
ImmutableList.of(c3), ImmutableList.of(c4));
List<Collection<Condition>> actual = new ArrayList<>();
for (ConditionQuery q : queries) {
actual.add(q.conditions());
}
@ -187,12 +186,12 @@ public class ConditionQueryFlattenTest extends BaseUnitTest {
Assert.assertEquals(1, query.conditions().size());
List<ConditionQuery> queries = ConditionQueryFlatten.flatten(query);
Assert.assertEquals(4, queries.size());
Set<Set<Condition>> expect;
expect = ImmutableSet.of(ImmutableSet.of(c1, c3),
ImmutableSet.of(c1, c4),
ImmutableSet.of(c2, c3),
ImmutableSet.of(c2, c4));
Set<Set<Condition>> actual = new HashSet<>();
List<Collection<Condition>> expect;
expect = ImmutableList.of(ImmutableList.of(c1, c3),
ImmutableList.of(c1, c4),
ImmutableList.of(c2, c3),
ImmutableList.of(c2, c4));
List<Collection<Condition>> actual = new ArrayList<>();
for (ConditionQuery q : queries) {
actual.add(q.conditions());
}
@ -211,10 +210,10 @@ public class ConditionQueryFlattenTest extends BaseUnitTest {
Assert.assertEquals(1, query.conditions().size());
List<ConditionQuery> queries = ConditionQueryFlatten.flatten(query);
Assert.assertEquals(2, queries.size());
Set<Set<Condition>> expect;
expect = ImmutableSet.of(ImmutableSet.of(c1, c2),
ImmutableSet.of(c3, c4));
Set<Set<Condition>> actual = new HashSet<>();
List<Collection<Condition>> expect;
expect = ImmutableList.of(ImmutableList.of(c1, c2),
ImmutableList.of(c3, c4));
List<Collection<Condition>> actual = new ArrayList<>();
for (ConditionQuery q : queries) {
actual.add(q.conditions());
}
@ -232,10 +231,10 @@ public class ConditionQueryFlattenTest extends BaseUnitTest {
List<ConditionQuery> queries = ConditionQueryFlatten.flatten(query);
Assert.assertEquals(3, queries.size());
Set<Condition> expect = ImmutableSet.of(Condition.eq(key, "1"),
Condition.eq(key, "2"),
Condition.eq(key, "3"));
Set<Condition> actual = new HashSet<>();
List<Condition> expect = ImmutableList.of(Condition.eq(key, "1"),
Condition.eq(key, "2"),
Condition.eq(key, "3"));
List<Condition> actual = new ArrayList<>();
for (ConditionQuery q : queries) {
Assert.assertEquals(1, q.conditions().size());
actual.add(q.conditions().iterator().next());
@ -254,10 +253,10 @@ public class ConditionQueryFlattenTest extends BaseUnitTest {
List<ConditionQuery> queries = ConditionQueryFlatten.flatten(query);
Assert.assertEquals(1, queries.size());
Set<Condition> expect = ImmutableSet.of(Condition.neq(key, "1"),
Condition.neq(key, "2"),
Condition.neq(key, "3"));
Set<Condition> actual = queries.iterator().next().conditions();
List<Condition> expect = ImmutableList.of(Condition.neq(key, "1"),
Condition.neq(key, "2"),
Condition.neq(key, "3"));
Collection<Condition> actual = queries.iterator().next().conditions();
Assert.assertEquals(expect, actual);
}
}