Creating property key schema

Creating or adding property key schema.

Property keys, as discussed in the data model, allow attribute values to be assigned to either vertices or edges. Property keys can also have property keys assigned to them as meta-properties using properties(). Property keys are defined before assigning them to vertex or edge labels, and indexes can be created based on property keys.

Properties will be used to retrieve selective subsets of the graph and to retrieve stored values. Properties are global in nature, and the pairing of a vertex label and a property will uniquely identify a property for use in traversals. Edge properties are expensive to update, because the whole edge, with all its properties, are deleted and recreated to update edge properties. Use edge properties only in situations that warrant their use.

The cardinality of a property key is single cardinality by default, but multiple cardinality can be assigned. Additionally, property keys can be created with a specific Time-To-Live (TTL) value. When creating property keys, prior existence of a key can be checked with ifNotExists().

Property keys must have a key name and data type assigned, at a minimum. Several data types exist to accommodate data storage in flexible formats. Some warrant special attention, such as geospatial and Cartesian. Three geospatial data types, point, linestring, and polygon, store data that can be searched with geospatial shapes. For most geospatial queries that look for geospatial points, points or linestrings within circles or polygons, DSE Search indexes must also be created; the same is true for Cartesian data types.

Property key schema are created with create(). Either DataStax Studio or the Gremlin console (dse gremlin-console) installed with DataStax Enterprise

can be used to create or modify property keys.

Prerequisites

Create a graph.

Procedure

Single and multiple cardinality property keys

  1. Define a single cardinality property key:
    The name of the propertyKey is personId, it is defined as an Integer type with Int(), with single cardinality explicitly stated with single():
    schema.propertyKey('personId').Int().single().create()
    Since single cardinality is the default, single() can be omitted:
    schema.propertyKey('personId').Int().create()
    To check if a property key already exists before creating it, use ifNotExists():
    schema.propertyKey('createDate').Date().single().ifNotExists().create()
  2. Define a multiple cardinality property key:
    The name of the propertyKey is nickname, it is defined as an Text type with Text(), with multiple cardinality:
    schema.propertyKey('nickname').Text().multiple().create()
    Since multiple cardinality is not the default, multiple() must be included.

Meta-properties

  1. Define a single cardinality meta-property to a multiple cardinality property key. First create the property keys for the meta-property, then create the property key that has the meta-property.
    The name of the meta-property propertyKey is since, it is defined as an Integer type with Int(), with single cardinality. The name of the propertyKey that uses this meta-property is badge, it is defined as an Text type with Text(), with multiple cardinality. The meta-property is defined with properties.
    // MULTIPLE CARDINALITY PROPERTY KEY WITH SINGLE CARDINALITY META-PROPERTY
    schema.propertyKey('since').Int().single().create() // meta-property
    schema.propertyKey('badge').Text().multiple().properties('since').create()
  2. Both properties and meta-properties can be defined with multiple cardinality. Define a multiple cardinality meta-property to a multiple cardinality property key. First create the property keys for the meta-property, then create the property key that has the meta-property.
    The name of the meta-property propertyKey is startYear, it is defined as an Integer type with Int(), with multiple cardinality. The name of the propertyKey that uses this meta-property is country, it is defined as an Text type with Text(), with multiple cardinality. The meta-property is defined with properties.
    // MULTIPLE CARDINALITY PROPERTY KEY WITH MULTIPLE CARDINALITY META-PROPERTY
    schema.propertyKey('startYear').Int().multiple().create()   // meta-property
    schema.propertyKey('endYear').Int().multiple().create()   // meta-property
    schema.propertyKey('country').Text().multiple().properties('startYear','endYear').create()
    This example includes two meta-properties, startYear and endYear.

Property keys with Time-To-Live (TTL)

  1. Property keys can be defined with a Time-To-Live (TTL) value; once the specified time is reached, the value is deleted from the graph. Define a single cardinality property key with TTL:
    The name of the propertyKey is bookDiscount, it is defined as an Text type with Text(), single cardinality (default), and a TTL of 604,800 seconds with ttl():
    // PROPERTY KEY WITH TTL
    schema.propertyKey('bookDiscount').Text().ttl(604800).create()

Geospatial property keys

  1. Create schema for point property key:
    schema.propertyKey('point').Point().withGeoBounds().create()
    Note: For all geospatial elements, the withGeoBounds() method limits searches to a default valid range of latitude in degrees from -90 to +90 (South Pole to North Pole) and a valid range of longitude in degrees from -180 to +180 (east to west from the Greenwich Meridian). The point is specified using Geo.point(longitude, latitude) when adding points, using WellKnownText (WKT) format. Note that is specifies longitude first, then latitude.
  2. Create schema for a linestring property key:
    schema.propertyKey('line').Linestring().withGeoBounds().create()
    The same boundary limits imposed on points are imposed on linestrings.
  3. Create schema for a polygon property key:
    schema.propertyKey('polygon').Polygon().withGeoBounds().create()
    The same boundary limits imposed on points are imposed on polygons.

Cartesian property keys

  1. Create schema for point property key:
    schema.propertyKey('point').Point().withBounds(-3, -3, 3, 3).create()
    Note: For Cartesian spatial types, the withBounds(x1, y1, x2, y2) method limit searches to a default valid range of values in the x-y grid.
  2. Create schema for a linestring property key:
    schema.propertyKey('line').Linestring().withBounds(-3, -3, 3, 3).create()
    The same boundary limits imposed on points are imposed on linestrings.
  3. Create schema for a polygon property key:
    schema.propertyKey('polygon').Polygon().withBounds(-3, -3, 3, 3).create()
    The same boundary limits imposed on points are imposed on polygons.
  4. Define the properties for the vertices and the edges. The data type of the property is specified in addition to a key name. All properties created in this example are Text, Integers, or Timestamps. Other data types are available. Properties will be used to retrieve selective subsets of the graph and to retrieve stored values. Properties are global in nature, and the pairing of a vertex label and a property will uniquely identify a property for use in traversals. Edge properties are expensive to update, as because the whole edge with all its properties are deleted and recreated to update edge properties. Use edge properties only in situations that warrant their use.
    // ********
    // PROPERTY KEYS
    // ********
    // SYNTAX:
    // propertyKey('name').
    //    type().
    //    [ single() | multiple() ].
    //    [ ttl ].
    //    [ properties(metadata_property) ].
    //    [ ifNotExists() ].
    //    [ create() | add() | describe() | exists() ]
    // DEFAULT IS SINGLE CARDINALITY
    // ********
    
    // SINGLE CARDINALITY PROPERTY KEY
    schema.propertyKey('personId').Int().single().create()
    schema.propertyKey('mealId').Int().single().create()
    schema.propertyKey('itemId').Int().single().create()
    schema.propertyKey('recipeId').Int().single().create()
    schema.propertyKey('bookId').Int().single().create()
    schema.propertyKey('ingredId').Int().single().create()
    schema.propertyKey('homeId').Int().single().create()
    schema.propertyKey('storeId').Int().single().create()
    schema.propertyKey('locId').Text().single().create()
    schema.propertyKey('stateId').Int().single().create()
    schema.propertyKey('cityId').Int().single().create()
    schema.propertyKey('sensorId').Int().single().create()
    schema.propertyKey('name').Text().single().create()
    schema.propertyKey('gender').Text().single().create()
    schema.propertyKey('calGoal').Int().single().create()
    schema.propertyKey('macroGoal').Text().single().create()
    schema.propertyKey('publishYear').Int().single().create()
    schema.propertyKey('ISBN').Text().single().create()
    // PROPERTY KEY WITH TTL
    schema.propertyKey('bookDiscount').Text().ttl(604800).create()
    schema.propertyKey('instructions').Text().single().create()
    schema.propertyKey('notes').Text().single().create()
    schema.propertyKey('type').Text().single().create()
    schema.propertyKey('servAmt').Text().single().create()
    schema.propertyKey('macro').Text().single().create()
    schema.propertyKey('calories').Int().single().create()
    schema.propertyKey('geoPoint').Point().withGeoBounds().create()
    schema.propertyKey('address').Text().single().create()
    schema.propertyKey('amount').Text().single().create()
    // MULTIPLE CARDINALITY PROPERTY KEY
    schema.propertyKey('nickname').Text().multiple().create()
    schema.propertyKey('cuisine').Text().multiple().create()
    // MULTIPLE CARDINALITY PROPERTY KEY WITH SINGLE CARDINALITY META-PROPERTY
    schema.propertyKey('since').Int().single().create() // meta-property
    schema.propertyKey('badge').Text().multiple().properties('since').create()
    // MULTIPLE CARDINALITY PROPERTY KEY WITH MULTIPLE CARDINALITY META-PROPERTY
    schema.propertyKey('startYear').Int().multiple().create()   // meta-property
    schema.propertyKey('endYear').Int().multiple().create()   // meta-property
    schema.propertyKey('country').Text().multiple().properties('startYear','endYear').create()
    
    // EDGE PROPERTIES
    schema.propertyKey('numServ').Int().single().create()
    schema.propertyKey('mealDate').Date().single().create()
    schema.propertyKey('useDate').Date().single().create()
    schema.propertyKey('createDate').Date().single().create()
    schema.propertyKey('expireDate').Date().single().create()
    schema.propertyKey('stars').Int().single().create()
    schema.propertyKey('time').Time().single().create()
    schema.propertyKey('year').Date().single().create()
    schema.propertyKey('comment').Text().single().create()
    // Property Keys 
    // Check for previous creation of property key with ifNotExists() 
    schema.propertyKey('name').Text().ifNotExists().create() 
    schema.propertyKey('gender').Text().create()
    schema.propertyKey('instructions').Text().create()
    schema.propertyKey('category').Text().create()
    schema.propertyKey('year').Int().create()
    schema.propertyKey('timestamp').Timestamp().create()
    schema.propertyKey('ISBN').Text().create()
    schema.propertyKey('calories').Int().create()
    schema.propertyKey('amount').Text().create()
    schema.propertyKey('stars').Int().create()
    schema.propertyKey('comment').Text().single().create() // single() is optional - default
    // Example of multiple property
    // schema.propertyKey('nickname').Text().multiple().create();
    // Example meta-property added to property: 
    // schema.propertyKey('livedIn').Text().create()
    // schema.propertyKey('country').Text().multiple().properties('livedIn').create()

    Property keys can be checked for prior existence with ifNotExists(). Property keys can be created with either single or multiple cardinality with single() or multiple(). The default is single cardinality which does not have to be specified, but it can be explicitly stated as in the example.

    Meta-properties, or properties of properties, can be created using propertyKey() followed by properties(). The property key must exist prior to the creation of a meta-property. Meta-properties cannot be nested, i.e., a meta-property cannot have a meta-property. In this example, country is the property that has a meta-property livedIn. This property and meta-property are used to represent the countries that an author has lived in at various times in their life.
    {
      "name":"Julia Child",
      "gender":"F",
      [ {"country": "United States", "livedIn": "1929-1949" }, {"country": "France", "livedIn": "1949-1952" } ], 
      "authored":[{
        "book":{
          "label":"book",
          "bookTitle":"Art of French Cooking Volume One",
          "publishDate":1968
        },
        "book":{
          "label":"book",
          "bookTitle":"The French Chef Cookbook",
          "publishDate":1968,
          "ISBN": "0-394-40135-2"
        }     
      }],
      "created": [{
        
          "type" : "recipe",
          "recipeTitle" : "BeefBourguignon",
          "instructions" : "Braise the beef.",
          "createDate":1967
        },
        { 
          "type" : "recipe",
          "recipeTitle" : "Salade Nicoise",
          "instructions" : "Break the lettuce into pieces.",
          "createDate": 1970
        }
      ]
    }

Example

// RECIPE SCHEMA

// To run in Studio, copy and paste all lines to a cell and run.

// To run in Gremlin console, use the next two lines:
// script = new File('/tmp/RecipeSchema.groovy').text; []
// :> @script
    	
// Property Keys 
// Check for previous creation of property key with ifNotExists() 
schema.propertyKey('name').Text().ifNotExists().create() 
schema.propertyKey('gender').Text().create()
schema.propertyKey('instructions').Text().create()
schema.propertyKey('category').Text().create()
schema.propertyKey('year').Int().create()
schema.propertyKey('timestamp').Timestamp().create()
schema.propertyKey('ISBN').Text().create()
schema.propertyKey('calories').Int().create()
schema.propertyKey('amount').Text().create()
schema.propertyKey('stars').Int().create()
schema.propertyKey('comment').Text().single().create() // single() is optional - default
// Example of multiple property
// schema.propertyKey('nickname').Text().multiple().create();
// Example meta-property added to property: 
// schema.propertyKey('livedIn').Text().create()
// schema.propertyKey('country').Text().properties('livedIn').create()
    		
// Vertex Labels
schema.vertexLabel('author').ifNotExists().create()
schema.vertexLabel('recipe').create()
// Example of creating vertex label with properties
// schema.vertexLabel('recipe').properties('name','instructions').create()
schema.vertexLabel('ingredient').create()
schema.vertexLabel('book').create()
schema.vertexLabel('meal').create()
schema.vertexLabel('reviewer').create()
// Example of custom vertex id:
// schema.propertyKey('city_id').Int().create()
// schema.propertyKey('sensor_id').Uuid().create()
// schema().vertexLabel('FridgeSensor').partitionKey('city_id').clusteringKey('sensor_id').create()
                
// Edge Labels
schema.edgeLabel('authored').ifNotExists().create()
schema.edgeLabel('created').create()
schema.edgeLabel('includes').create()
schema.edgeLabel('includedIn').create()
schema.edgeLabel('rated').properties('stars').connection('reviewer','recipe').create()
                
// Vertex Indexes
// Secondary
schema.vertexLabel('author').index('byName').secondary().by('name').add()
// Materialized	  		
schema.vertexLabel('recipe').index('byRecipe').materialized().by('name').add()
schema.vertexLabel('meal').index('byMeal').materialized().by('name').add()
schema.vertexLabel('ingredient').index('byIngredient').materialized().by('name').add()
schema.vertexLabel('reviewer').index('byReviewer').materialized().by('name').add()
// Search
// schema.vertexLabel('recipe').index('search').search().by('instructions').asText().add()
// schema.vertexLabel('recipe').index('search').search().by('instructions').asString().add()
// If more than one property key is search indexed
// schema.vertexLabel('recipe').index('search').search().by('instructions').asText().by('category').asString().add()

// Edge Index
schema.vertexLabel('reviewer').index('ratedByStars').outE('rated').by('stars').add()

// Example of property index using meta-property 'livedIn': 
// schema().vertexLabel('author').index('byLocation').property('country').by('livedIn').add()

// Schema description
// Use to check that the schema is built as desired
schema.describe()