Gremlin multi-valued property examples

Updated at:

This topic provides examples of Gremlin multi-valued properties.

Multi-valued properties

  • Gremlin syntax supports multi-valued properties for vertices. When you add or update a property, you can specify the property type using the cardinality parameter.

  • Gremlin provides two types of multi-valued properties: set and list. GDB supports set properties starting from version 1.0.20.

Notes

  • Only vertices support multi-valued properties. Edges do not.

  • The values of a set property can be of different data types. However, GDB compares values based on their semantics to check for equality. Two values of different types are considered equal if their values are the same, such as 1 and 1.0. In this case, only one value is kept.

  • The cardinality of a property can be changed. The last call to property() determines the final cardinality. If a set property is updated to a single-value type, only the new value is kept. If a single-value property is updated to a set type, both the old and new values are kept.

  • Multiple values in the query result of a set property are sorted by semantics. Numeric values are sorted in ascending order. String values are sorted in lexicographic order.

  • Similar to single-value properties, set properties are automatically indexed. Their query performance is similar to that of single-value properties.

Set property usage

Console

  • Set a property

    g.addV('person').
    property(id, '11111').
    property('name', 'marko').
    property(set, 'email', 'marko@a.com').
    property(set, 'email', 'marko@b.com')
  • Query a property

    g.V('11111').properties('email')
    ==>vp[email->marko@a.com]
    ==>vp[email->marko@b.com]
  • Delete a value

    g.V('11111').properties('email').hasValue('marko@a.com').drop()
  • Delete all values

    g.V('11111').properties('email').drop()

Java

package com.gdb.alibaba;

import org.apache.tinkerpop.gremlin.driver.Cluster;
import org.apache.tinkerpop.gremlin.driver.Client;
import org.apache.tinkerpop.gremlin.driver.Result;
import org.apache.tinkerpop.gremlin.driver.ResultSet;
import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertex;
import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertexProperty;

import java.util.List;
import java.util.Map;
import java.util.HashMap;
import java.io.File;

public class Test {
  public static void main(String[] args) {
    try {
      if (args.length != 1) {
        System.out.println("gdb-remote.yaml path needed");
        return;
      }
      String yaml = args[0];
      Cluster cluster = Cluster.build(new File(yaml)).create();
      Client client = cluster.connect().init();
      String dsl = "g.addV(yourLabel).property(propertyKey, propertyValue).property(set, setPropertyKey, setPropertyValue0).property(set, setPropertyKey, setPropertyValue1)";
      Map<String, Object> parameters = new HashMap<>();
      parameters.put("yourLabel", "person");
      parameters.put("propertyKey", "name");
      parameters.put("propertyValue", "marko");
      parameters.put("setPropertyKey", "email");
      parameters.put("setPropertyValue0", "marko@a.com");
      parameters.put("setPropertyValue1", "marko@b.com");
      ResultSet results = client.submit(dsl, parameters);
      List<Result> result = results.all().join();
      if (result.size() > 0) {
        String vertexId = (String) ((DetachedVertex) result.get(0).getObject()).id();
        parameters.put("yourId", vertexId);
      }

      dsl = "g.V(yourId).properties(setPropertyKey)";
      results = client.submit(dsl, parameters);
      result = results.all().join();
      result.forEach(r -> {
        Object element = r.getObject();
        if (element instanceof DetachedVertexProperty) {
          DetachedVertexProperty property = (DetachedVertexProperty) element;
          System.out.println(property.key() + ": " + property.value());
        }
      });

      cluster.close();
    } catch (Exception e) {
      System.out.println(e.getMessage());
    }
  }
}

Python

  • Usage 1:

    from gremlin_python.process.anonymous_traversal import traversal
    from gremlin_python.driver.driver_remote_connection import DriverRemoteConnection
    from gremlin_python.process.traversal import T, Cardinality
    
    g = traversal().withRemote(
        DriverRemoteConnection('ws://HOST:PORT/gremlin',
                               'g',
                               username=USER,
                               password=PASS))
    
    v = g.addV('person').property(T.id_, "123").property("name", "marko") \
        .property(Cardinality.set_, "email", "marko@gmail.com") \
        .property(Cardinality.set_, "email", "marko@hotmail.com").iterate()
    
    properties = g.V('123').properties('email')
    for prop in properties:
        print(prop.key + ": " + str(prop.value))
    
    g.V('123').drop().iterate()
  • Usage 2:

    from gremlin_python.driver import client
    
    client = client.Client('ws://HOST:PORT/gremlin',
                           'g',
                           username=USER,
                           password=PASS)
    
    dsl = 'g.addV("person").property(id, "123").property("name", "marko").property(set, "email", "marko@a.com").property(set, "email", "marko@b.com")'
    callback = client.submitAsync(dsl)
    for result in callback.result():
        print(result)
    
    dsl = 'g.V("123").properties("email")'
    callback = client.submitAsync(dsl)
    for result in callback.result():
        for prop in result:
            print(prop.key + ": " + str(prop.value))

Go

    bindings := make(map[string]interface{})
    bindings["GDB___id"] = "22"
    bindings["GDB___label"] = "goTest"
    bindings["GDB___PK"] = "name"
    bindings["GDB___PV"] = "Jack"
    bindings["GDB___PK_PHONE"] = "phone"
    bindings["GDB___PV_PHONE1"] = "111111"
    bindings["GDB___PV_PHONE2"] = "222222"

    dsl := "g.addV(GDB___label).property(id, GDB___id).property(GDB___PK, GDB___PV).property(set, GDB___PK_PHONE, GDB___PV_PHONE1).property(set, GDB___PK_PHONE, GDB___PV_PHONE2)"
    results, err := client.SubmitScriptBound(dsl, bindings)
    if err != nil {
        log.Fatalf("Error while querying: %s\n", err.Error())
    }

    // get response, add vertex should return a Vertex
    for _, result := range results {
        v := result.GetVertex()
        log.Printf("get vertex: %s", v.String())

        // read vertex property
        for _, p := range v.VProperties() {
            log.Printf("prop: %s", p.String())
        }
    }

Javascript

const gremlin = require('gremlin');
const DriverRemoteConnection = gremlin.driver.DriverRemoteConnection;
const Graph = gremlin.structure.Graph;
const __ = gremlin.process.statics;
const t = gremlin.process.t;
const cardinality = gremlin.process.cardinality
const authenticator =
    new gremlin.driver.auth.PlainTextSaslAuthenticator(USER, PASS);

const graph = new Graph();
const g = graph.traversal().withRemote(
    new DriverRemoteConnection('ws://HOST:PORT/gremlin', {authenticator}));

g.addV('person')
      .property(t.id, '2222')
      .property('name', 'james')
      .property(cardinality.set, 'phone', '111111')
      .property(cardinality.set, 'phone', '222222')
      .iterate()
      .then(data => {
        g.V('2222').properties().toList().then(
            properties => { console.log(properties); });
      });