Skip to content
seanbarzilay edited this page Oct 15, 2017 · 1 revision

Mapping A Rest Data Store

In order to map a rest data store you will need to get familiar with both Mustache and JMustache.
After you are familiar with Mustache you can start writing your templates.

Templates

Search Template

The search template will generate a query for your rest data store.
Your template will generate with a json that will look like:

{
  "limit": 100000,
  "predicates": {
    "and": {
      "predicates": [
        {"op": "op", "value": "value", "key": "key"}
      ],
      "complex": ["complex_operation"],
      "children":[
        {
          "predicates": {
            "and": {},
            "or": {}
          }
        }
      ]
    },
    "or": {
      "predicates": [
        {"op": "op", "value": "value", "key": "key"}
      ],
      "complex": ["complex_operation"],
      "children":[
        {
          "predicates": {
            "and": {},
            "or": {}
          }
        }
      ]
    }
  }
}

The search template can be used as a sub template to generate the child constraints.
You don't have to support every operation, what you'r not supporting will just be done in memory sometimes in the expense of performance.
For example you can refer to the elastic search template which supports all the operations.

Add Template

The add template will generate an add query for your rest data store.
Your template will generate with a json that will look like:

{
  "prop":[
    {
      "key": "key",
      "value": "value"
    }
  ]
}

Bulk Template

The bulk template can generate a bulk insertion if you support it and uses the add template as a sub template.
Your template will generate with a json that will look like:

{
  "bulk": [
    {
      "url": {"resource": "resource", "type": "type", "id": "id"},
      "object": {
        "prop": [
          {
            "key": "key",
            "value": "value"
          }
        ]
      }
    }
  ]
}

You don't have to implement anything you don't intend to use.

Unipop Mapping

To map data from a rest data store your mapping file will look like:

{
  "class": "org.unipop.rest.RestSourceProvider",
  "baseUrl": "http://your.url",
  "add":{
    "url": "/{{resource}}/{{type}}/{{id}}",
    "template": "{ {{#prop}}\"{{key}}\":\"{{value}}\"{{^-last}}, {{/-last}}{{/prop}} }",
    "commit": {
      "url":"/{{resource}}/_refresh"
    },
      "bulk":{
        "url": "/_bulk",
        "template": "resources/bulk.mustache"
      }
    },
    "search":{
      "url": "{{resource}}/_search",
      "template": "resources/search.mustache"
    },
    "delete":{
      "url" : "{{resource}}/{{type}}/{{id}}"
  },
  "resultPath": "hits.hits",
  "opTranslator": {
    "eq": "term",
    "within": "terms"
  },
  "complexTranslator":[
      {"op": "gt", "template": "{ \"range\": { {{key}}: { \"gt\": {{value}} } } }"}
  ],
  "vertices": [],
  "edges": []
}

This example is specifically for elasticsearch.

  • baseUrl - The base url for all of your queries.
  • add - Optional, the add query template contains a url template which will be concatenated to the base url
    at query time, the template itself, commit url if necessary and bulk template also optional.
  • search - Your search template contains a url template and the template itself.
  • delete - Optional, delete url template.
  • resultPath - The path to the result in the returned JSON.
  • opTranslator - Translate gremlin operations to keywords for your query, basic queries that are built the same.
  • complexTranslator - Translate complex operations where each operation, complex queries that built differently.

Every template can be written inline or as a file path.

Complex Translator

Each complex operator is chosen by a matcher.
We currently have three matchers available.

  • Op Matcher - Chosen by the operation of the predicate.
{"op": "some_operation", "template": "some_template"}
  • Multi Op Matcher - Like op matcher but for multiple operations.
{"ops": ["some_operation1", "some_operation2"], "template": "some_template"}
  • Key Matcher - Chosen by the key of the predicate.
{"key": "some_key", "template": "some_template"}

Mapping Elements

Each element we map requires some more information from us about it's whereabouts, we'll need to provide a resource.

{
  "resource": "a_resource"
}

So a vertex will look like:

{
  "resource": "a_resource",
  "id": "an_id",
  "label": "a_label",
  "properties": {}
}

If we require each field can be represented as a path.
ie. in elasticsearch it will look something like '@_source.someField'.

An edge will look like:

{
  "resource": "a_resource",
  "id": "an_id",
  "label": "a_label",
  "properties": {},
  "outVertex": {
    "ref": true,
    "id": "out_vertex_id",
    "label": "out_vertex_label"
  },
  "inVertex": {
      "ref": true,
      "id": "in_vertex_id",
      "label": "in_vertex_label"
    }
}

Currently only one way to represent an edge from a rest data source is available.