Query的查询主要有以下几个实现:
Condition的主要分为四类
NONE,
RELATION,
AND,
OR;
RelationType的代码极其风骚
EQ("==", (v1, v2) -> {return equals(v1, v2); }),
GT(">", (v1, v2) -> { return compare(v1, v2) > 0; }),
GTE(">=", (v1, v2) -> { return compare(v1, v2) >= 0; }),
LT("<", (v1, v2) -> { return compare(v1, v2) < 0; }),
LTE("<=", (v1, v2) -> { return compare(v1, v2) <= 0; }),
NEQ("!=", (v1, v2) -> { return compare(v1, v2) != 0; }),
IN("in", null, Collection.class, (v1, v2) -> {
assert v2 != null;
return ((Collection<?>) v2).contains(v1);
}),
NOT_IN("notin", null, Collection.class, (v1, v2) -> {
assert v2 != null;
return !((Collection<?>) v2).contains(v1);
}),
PREFIX("prefix", Id.class, Id.class, (v1, v2) -> {
assert v2 != null;
return v1 != null && Bytes.prefixWith(((Id) v2).asBytes(),
((Id) v1).asBytes());
}),
TEXT_CONTAINS("textcontains", String.class, String.class, (v1, v2) -> {
return v1 != null && ((String) v1).contains((String) v2);
}),
TEXT_CONTAINS_ANY("textcontainsany", String.class, Collection.class,
(v1, v2) -> {
assert v2 != null;
if (v1 == null) {
return false;
}
@SuppressWarnings("unchecked")
Collection<String> words = (Collection<String>) v2;
for (String word : words) {
if (((String) v1).contains(word)) {
return true;
}
}
return false;
}),
CONTAINS("contains", Collection.class, null, (v1, v2) -> {
assert v2 != null;
return v1 != null && ((Collection<?>) v1).contains(v2);
}),
CONTAINS_VALUE("containsv", Map.class, null, (v1, v2) -> {
assert v2 != null;
return v1 != null && ((Map<?, ?>) v1).containsValue(v2);
}),
CONTAINS_KEY("containsk", Map.class, null, (v1, v2) -> {
assert v2 != null;
return v1 != null && ((Map<?, ?>) v1).containsKey(v2);
}),
SCAN("scan", (v1, v2) -> {
assert v2 != null;
/*
* TODO: we still have no way to determine accurately, since
* some backends may scan with token(column) like cassandra.
*/
return true;
});
借用了lambda 和BiPredicate 进行条件的比较。这是RELATEION_TYPE的比较后边都会用到。
接下来是Relation
我们看Condition,Realation 的实现都是用的SyspropRelation 和UserpropRelation的实现。
public static Relation eq(Id key, Object value) {
return new UserpropRelation(key, RelationType.EQ, value);
}
public static Relation gt(Id key, Object value) {
return new UserpropRelation(key, RelationType.GT, value);
}
public static Relation gte(Id key, Object value) {
return new UserpropRelation(key, RelationType.GTE, value);
}
public static Relation lt(Id key, Object value) {
return new UserpropRelation(key, RelationType.LT, value);
}
public static Relation lte(Id key, Object value) {
return new UserpropRelation(key, RelationType.LTE, value);
}
public static Relation neq(Id key, Object value) {
return new UserpropRelation(key, RelationType.NEQ, value);
}
public static Relation in(Id key, List<?> value) {
return new UserpropRelation(key, RelationType.IN, value);
}
public static Relation nin(Id key, List<?> value) {
return new UserpropRelation(key, RelationType.NOT_IN, value);
}
public static Relation textContains(Id key, String word) {
return new UserpropRelation(key, RelationType.TEXT_CONTAINS, word);
}
public static Relation textContainsAny(Id key, Set<String> words) {
return new UserpropRelation(key, RelationType.TEXT_CONTAINS_ANY, words);
}
可以看到用的是静态方法实现也比较简洁。
UserpropRelation的实现我们具体看下
public static class UserpropRelation extends Relation {
// Id of property key
private Id key;
public UserpropRelation(Id key, Object value) {
this(key, RelationType.EQ, value);
}
public UserpropRelation(Id key, RelationType op, Object value) {
E.checkNotNull(op, "relation type");
this.key = key;
this.relation = op;
this.value = value;
}
@Override
public Id key() {
return this.key;
}
@Override
public boolean isSysprop() {
return false;
}
@Override
public boolean test(HugeElement element) {
HugeProperty<?> prop = element.getProperty(this.key);
Object value = prop != null ? prop.value() : null;
if (value == null) {
/*
* Fix #611
* TODO: It's possible some scenes can't be returned false
* directly, such as: EQ with p1 == null, it should be returned
* true, but the query has(p, null) is not allowed by
* TraversalUtil.validPredicateValue().
*/
return false;
}
return this.relation.test(value, this.value());
}
@Override
public Condition copy() {
Relation clone = new UserpropRelation(this.key, this.relation(),
this.value);
clone.serialKey(this.serialKey);
clone.serialValue(this.serialValue);
return clone;
}
}
其实最关键的是test的但方法,检验传进来的两个值之间的realation_type.
我们来具体看下Query 是如何从前到后执行的。一个测试的案例
Assert.assertThrows(HugeException.class, () -> {
ConditionQuery query = new ConditionQuery(HugeType.VERTEX);
query.eq(HugeKeys.LABEL, author);
query.eq(HugeKeys.NAME, "n1");
graph.vertices(query).hasNext();
}, e -> {
Assert.assertContains("Not supported querying vertices by",
e.getMessage());
Assert.assertContains("NAME == n1", e.getMessage());
});
本文由 妖言君 创作,采用 知识共享署名4.0 国际许可协议进行许可
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
最后编辑时间为: Apr 3, 2022 at 11:59 am