hugegraph query查询(六)
in with 0 comment

hugegraph query查询(六)

in with 0 comment

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());
        });
Responses