use of com.baidu.hugegraph.backend.query.Condition in project incubator-hugegraph by apache.
the class GraphTransaction method optimizeQuery.
private Query optimizeQuery(ConditionQuery query) {
if (query.idsSize() > 0) {
throw new HugeException("Not supported querying by id and conditions: %s", query);
}
Id label = (Id) query.condition(HugeKeys.LABEL);
// Optimize vertex query
if (label != null && query.resultType().isVertex()) {
VertexLabel vertexLabel = this.graph().vertexLabel(label);
if (vertexLabel.idStrategy() == IdStrategy.PRIMARY_KEY) {
List<Id> keys = vertexLabel.primaryKeys();
E.checkState(!keys.isEmpty(), "The primary keys can't be empty when using " + "'%s' id strategy for vertex label '%s'", IdStrategy.PRIMARY_KEY, vertexLabel.name());
if (query.matchUserpropKeys(keys)) {
// Query vertex by label + primary-values
query.optimized(OptimizedType.PRIMARY_KEY);
String primaryValues = query.userpropValuesString(keys);
LOG.debug("Query vertices by primaryKeys: {}", query);
// Convert {vertex-label + primary-key} to vertex-id
Id id = SplicingIdGenerator.splicing(label.asString(), primaryValues);
/*
* Just query by primary-key(id), ignore other userprop(if
* exists) that it will be filtered by queryVertices(Query)
*/
return new IdQuery(query, id);
}
}
}
// Optimize edge query
if (query.resultType().isEdge() && label != null && query.condition(HugeKeys.OWNER_VERTEX) != null && query.condition(HugeKeys.DIRECTION) != null && matchEdgeSortKeys(query, false, this.graph())) {
// Query edge by sourceVertex + direction + label + sort-values
query.optimized(OptimizedType.SORT_KEYS);
query = query.copy();
// Serialize sort-values
List<Id> keys = this.graph().edgeLabel(label).sortKeys();
List<Condition> conditions = GraphIndexTransaction.constructShardConditions(query, keys, HugeKeys.SORT_VALUES);
query.query(conditions);
/*
* Reset all userprop since transferred to sort-keys, ignore other
* userprop(if exists) that it will be filtered by queryEdges(Query)
*/
query.resetUserpropConditions();
LOG.debug("Query edges by sortKeys: {}", query);
return query;
}
/*
* Query only by sysprops, like: by vertex label, by edge label.
* NOTE: we assume sysprops would be indexed by backend store
* but we don't support query edges only by direction/target-vertex.
*/
if (query.allSysprop()) {
if (query.resultType().isVertex()) {
verifyVerticesConditionQuery(query);
} else if (query.resultType().isEdge()) {
verifyEdgesConditionQuery(query);
}
/*
* Just support:
* 1.not query by label
* 2.or query by label and store supports this feature
*/
boolean byLabel = (label != null && query.conditionsSize() == 1);
if (!byLabel || this.store().features().supportsQueryByLabel()) {
return query;
}
}
return null;
}
use of com.baidu.hugegraph.backend.query.Condition in project incubator-hugegraph by apache.
the class GraphIndexTransaction method constructShardConditions.
protected static List<Condition> constructShardConditions(ConditionQuery query, List<Id> fields, HugeKeys key) {
List<Condition> conditions = new ArrayList<>(2);
boolean hasRange = false;
int processedCondCount = 0;
List<Object> prefixes = new ArrayList<>();
for (Id field : fields) {
List<Condition> fieldConds = query.userpropConditions(field);
processedCondCount += fieldConds.size();
if (fieldConds.isEmpty()) {
break;
}
RangeConditions range = new RangeConditions(fieldConds);
if (!range.hasRange()) {
E.checkArgument(range.keyEq() != null, "Invalid query: %s", query);
prefixes.add(range.keyEq());
continue;
}
if (range.keyMin() != null) {
RelationType type = range.keyMinEq() ? RelationType.GTE : RelationType.GT;
conditions.add(shardFieldValuesCondition(key, prefixes, range.keyMin(), type));
} else {
assert range.keyMax() != null;
Object num = range.keyMax();
num = NumericUtil.minValueOf(NumericUtil.isNumber(num) ? num.getClass() : Long.class);
conditions.add(shardFieldValuesCondition(key, prefixes, num, RelationType.GTE));
}
if (range.keyMax() != null) {
RelationType type = range.keyMaxEq() ? RelationType.LTE : RelationType.LT;
conditions.add(shardFieldValuesCondition(key, prefixes, range.keyMax(), type));
} else {
Object num = range.keyMin();
num = NumericUtil.maxValueOf(NumericUtil.isNumber(num) ? num.getClass() : Long.class);
conditions.add(shardFieldValuesCondition(key, prefixes, num, RelationType.LTE));
}
hasRange = true;
break;
}
/*
* Can't have conditions after range condition for shard index,
* but SORT_KEYS can have redundant conditions because upper
* layer can do filter.
*/
if (key == HugeKeys.FIELD_VALUES && processedCondCount < query.userpropKeys().size()) {
throw new HugeException("Invalid shard index query: %s", query);
}
// 1. First range condition processed, finish shard query conditions
if (hasRange) {
return conditions;
}
// 2. Shard query without range
String joinedValues;
// 2.1 All fields have equal-conditions
if (prefixes.size() == fields.size()) {
// Prefix numeric values should be converted to sortable string
joinedValues = ConditionQuery.concatValues(prefixes);
conditions.add(Condition.eq(key, joinedValues));
return conditions;
}
// 2.2 Prefix fields have equal-conditions
/*
* Append EMPTY to 'values' to ensure FIELD_VALUES suffix
* with IdGenerator.NAME_SPLITOR
*/
prefixes.add(ConditionQuery.INDEX_VALUE_EMPTY);
joinedValues = ConditionQuery.concatValues(prefixes);
Condition min = Condition.gte(key, joinedValues);
conditions.add(min);
// Increase 1 on prefix to get the next prefix
Condition max = Condition.lt(key, increaseString(joinedValues));
conditions.add(max);
return conditions;
}
use of com.baidu.hugegraph.backend.query.Condition in project incubator-hugegraph by apache.
the class GraphIndexTransaction method constructQuery.
private static ConditionQuery constructQuery(ConditionQuery query, IndexLabel indexLabel) {
IndexType indexType = indexLabel.indexType();
boolean requireRange = query.hasRangeCondition();
boolean supportRange = indexType.isNumeric();
if (requireRange && !supportRange) {
LOG.debug("There is range query condition in '{}', " + "but the index label '{}' is unable to match", query, indexLabel.name());
return null;
}
Set<Id> queryKeys = query.userpropKeys();
List<Id> indexFields = indexLabel.indexFields();
if (!matchIndexFields(queryKeys, indexFields)) {
return null;
}
LOG.debug("Matched index fields: {} of index '{}'", indexFields, indexLabel);
ConditionQuery indexQuery;
switch(indexType) {
case SEARCH:
E.checkState(indexFields.size() == 1, "Invalid index fields size for %s: %s", indexType, indexFields);
Object fieldValue = query.userpropValue(indexFields.get(0));
assert fieldValue instanceof String;
// Will escape special char inside concatValues()
fieldValue = ConditionQuery.concatValues(fieldValue);
indexQuery = new ConditionQuery(indexType.type(), query);
indexQuery.eq(HugeKeys.INDEX_LABEL_ID, indexLabel.id());
indexQuery.eq(HugeKeys.FIELD_VALUES, fieldValue);
break;
case SECONDARY:
List<Id> joinedKeys = indexFields.subList(0, queryKeys.size());
// Will escape special char inside userpropValuesString()
String joinedValues = query.userpropValuesString(joinedKeys);
indexQuery = new ConditionQuery(indexType.type(), query);
indexQuery.eq(HugeKeys.INDEX_LABEL_ID, indexLabel.id());
indexQuery.eq(HugeKeys.FIELD_VALUES, joinedValues);
break;
case RANGE_INT:
case RANGE_FLOAT:
case RANGE_LONG:
case RANGE_DOUBLE:
if (query.userpropConditions().size() > 2) {
throw new HugeException("Range query has two conditions at most, " + "but got: %s", query.userpropConditions());
}
// Replace the query key with PROPERTY_VALUES, set number value
indexQuery = new ConditionQuery(indexType.type(), query);
indexQuery.eq(HugeKeys.INDEX_LABEL_ID, indexLabel.id());
for (Condition condition : query.userpropConditions()) {
assert condition instanceof Condition.Relation;
Condition.Relation r = (Condition.Relation) condition;
Number value = NumericUtil.convertToNumber(r.value());
Condition.Relation sys = new Condition.SyspropRelation(HugeKeys.FIELD_VALUES, r.relation(), value);
condition = condition.replace(r, sys);
indexQuery.query(condition);
}
break;
case SHARD:
HugeType type = indexLabel.indexType().type();
indexQuery = new ConditionQuery(type, query);
indexQuery.eq(HugeKeys.INDEX_LABEL_ID, indexLabel.id());
List<Condition> conditions = constructShardConditions(query, indexLabel.indexFields(), HugeKeys.FIELD_VALUES);
indexQuery.query(conditions);
break;
default:
throw new AssertionError(String.format("Unknown index type '%s'", indexType));
}
/*
* Set limit for single index or composite index, also for joint index,
* to avoid redundant element ids and out of capacity.
* NOTE: not set offset because this query might be a sub-query,
* see queryByUserprop()
*/
indexQuery.page(query.page());
indexQuery.limit(query.total());
indexQuery.capacity(query.capacity());
indexQuery.olap(indexLabel.olap());
return indexQuery;
}
use of com.baidu.hugegraph.backend.query.Condition in project incubator-hugegraph by apache.
the class RamTable method matched.
@Watched
public boolean matched(Query query) {
if (this.edgesSize() == 0L || this.loading) {
return false;
}
if (!query.resultType().isEdge() || !(query instanceof ConditionQuery)) {
return false;
}
ConditionQuery cq = (ConditionQuery) query;
int conditionsSize = cq.conditionsSize();
Object owner = cq.condition(HugeKeys.OWNER_VERTEX);
Directions direction = cq.condition(HugeKeys.DIRECTION);
Id label = cq.condition(HugeKeys.LABEL);
if (direction == null && conditionsSize > 1) {
for (Condition cond : cq.conditions()) {
if (cond.equals(BOTH_COND)) {
direction = Directions.BOTH;
break;
}
}
}
int matchedConds = 0;
if (owner != null) {
matchedConds++;
} else {
return false;
}
if (direction != null) {
matchedConds++;
}
if (label != null) {
matchedConds++;
}
return matchedConds == cq.conditionsSize();
}
use of com.baidu.hugegraph.backend.query.Condition in project incubator-hugegraph by apache.
the class ScyllaDBTablesWithMV method isQueryBySpecifiedKey.
private static boolean isQueryBySpecifiedKey(Query query, HugeKeys key) {
Collection<Condition> conditions = query.conditions();
if (query instanceof ConditionQuery && !conditions.isEmpty()) {
ConditionQuery cq = (ConditionQuery) query;
Object value = cq.condition(key);
return value != null && cq.allSysprop() && conditions.size() == 1 && cq.containsRelation(key, Condition.RelationType.EQ);
}
return false;
}
Aggregations