cypher-for-gremlin icon indicating copy to clipboard operation
cypher-for-gremlin copied to clipboard

Multilable issues

Open mad opened this issue 6 years ago • 3 comments

First, if we use multilable options, that labels not sorted, and we have some problem during queries Second, if we try search vertices with partial label, that found nothing

I trying reconfigure that behaviour just extends TraversalGremlinSteps, and rewrite label specific methods. This work for me right, but may be rewritten more clearly

private static class MultipleLabelsTraversalGremlinSteps extends TraversalGremlinSteps {

        private final GraphTraversal g;

        MultipleLabelsTraversalGremlinSteps(GraphTraversal g) {
            super(g);
            this.g = g;
        }

        @Override
        public GremlinSteps<GraphTraversal, P> hasLabel(String... labels) {
            List<String> sortedLabels = new ArrayList<>();
            for (String label : labels) {
                sortedLabels.add(sortLabels(label));
            }

            if (labels.length == 1 && !labels[0].contains("::")) {
                g.hasLabel(LabelP.of(labels[0]));
                return this;
            }

            return super.hasLabel(sortedLabels.toArray(new String[0]));
        }

        @Override
        public GremlinSteps<GraphTraversal, P> label() {
            return super.label();
        }

        @Override
        public GremlinSteps<GraphTraversal, P> addV(String vertexLabel) {
            vertexLabel = sortLabels(vertexLabel);
            return super.addV(vertexLabel);
        }

        @Override
        public GremlinSteps<GraphTraversal, P> hasKey(String... labels) {
            List<String> sortedLabels = new ArrayList<>();
            for (String label : labels) {
                sortedLabels.add(sortLabels(label));
            }
            return super.hasKey(sortedLabels.toArray(new String[0]));
        }

        private String sortLabels(String vertexLabel) {
            if (vertexLabel.contains("::")) {
                String[] labels = vertexLabel.split("::");
                Arrays.sort(labels);
                StringJoiner sortedLabels = new StringJoiner("::");
                for (String s : labels) {
                    sortedLabels.add(s);
                }
                vertexLabel = sortedLabels.toString();
            }
            return vertexLabel;
        }
    }

LabelP predicate from package org.apache.tinkerpop:neo4j-gremlin:3.3.3, that proper handle partial label

mad avatar Aug 30 '18 08:08 mad

Hello @mad,

currently Cypher for Gremlin has limited support of multiple labels, and works differently depending on target, because multiple label feature is not part of Gremlin, so each implementation (Neo4j, Neptune) has its own specifics.

I would be able to provide more information if you clarify which implementation (and version) of Gremlin Server you are planning to use?

Your example looks specific to Neo4j-Gremlin. Is this for test-only purposes?

dwitry avatar Aug 30 '18 11:08 dwitry

JanusGraph 0.3.0 implementation

mad avatar Aug 30 '18 12:08 mad

Multiple label feature is not supported in JanusGraph. Cypher for Gremlin API enableMultipleLabels enables limited support on implementations that support this feature (e.g. Neptune).

Note for others who might be reading this - it works because on creation multiple labels are concatenated to a single one. Predicate LabelP allow matching such labels. Same could be achieved by using textRegex predicate.

Using predicate in hasLabel is an interesting idea. We will evaluate it and consider adding predicate like LabelP to Extensions. This will allow to partially emulate multiple label functionality even on Gremlin Server implementations that does not support it.

As modification of node labels will unlikely to be supported in CfoG and Cypher appears to be sorting node labels, it makes sense to apply sorting on creation as in your example. 

Thank you for suggestions.

dwitry avatar Aug 30 '18 14:08 dwitry