Skip to content

Data requests

DanielHabenicht edited this page Feb 5, 2022 · 9 revisions

In Syncmesh, there is one unified way to query, mutate and aggregate data: The Syncmesh Request.

General Structure

The query has the following parameters:

  • "query": Contains the GraphQL query
  • "variables": dictionary type to specify GraphQL query variables (optional)
  • "database": Specifies the MongoDB database to query on (optional, default value is "syncmesh")
  • "collection": Specifies the MongoDB collection to query on (optional, default value is "sensor_data")
  • "request_type": Specifies the SyncMesh request type. Currently, "aggregate" and "collect" are supported.
  • "external_nodes": list of all addressable external SyncMesh nodes for data collection/aggregation (optional)
  • "use_meta_data": boolean whether the stored syncmesh metadata of external nodes should be used for collection/aggregation (optional, default is false)
  • "radius": range filter in kilometers, applied to stored external nodes (optional)

Let's take a look at available operations:

Collection queries

With collection queries, the GraphQL function sensors is used. you can set a limit and a start_time or end_time. all three parameters are optional, if none are used, all documents in the collection are returned.

An example query for a specific time range with a limit of 10 documents:

{
  "query": "{sensors(limit: 10, start_time: \"2017-07-30T00:00:00Z\", end_time: \"2017-07-31T00:00:00Z\"){temperature humidity timestamp}}",
  "database": "syncmesh",
  "collection": "sensor_data",
  "request_type": "collect"
}

A query for a collection with external nodes looks like this:

{
  "query": "{sensors(limit: 1, start_time: \"2017-06-26T00:00:00Z\", end_time: \"2017-08-01T00:00:00Z\"){temperature humidity timestamp}}",
  "database": "syncmesh",
  "collection": "sensor_data",
  "request_type": "collect",
  "external_nodes": ["http://some.random.ip:8080/function/syncmesh-fn"]
}

Notice that the return will be 2 entries, since the query limit of 1 applies to each node, end the result is a combination of all queries.

For fetching a single document, sensor instead of sensors is used.

An example query fetching a document with a specific ID:

{
  "query": "{sensor(_id: \"60e0615f39dc2d7833bdb9c9\"){temperature}}",
  "database": "syncmesh",
  "collection": "sensor_data",
  "request_type": "collect"
}

Querying with variables

You can also use variables instead of writing everything into the query. An advantage of doing this is you have shorter lines in the request, you also don't need to escape strings. An example for querying a document with an ID:

{
  "query": "query sensor($id: ID!){sensor(_id: $id){temperature}}",
  "database": "syncmesh",
  "variables": {
    "id": "60e9a27ec17cbf8c64ee8796"
  },
  "collection": "sensor_data",
  "request_type": "collect"
}

If you are interested in the specific variable syntax, read the official GraphQL documentation.

Aggregation query

Aggregation queries combine the data into average values. For this, we use sensorsAggregate with optional start and end time values:

{
  "query": "{sensorsAggregate(start_time: \"2017-06-26T00:00:00Z\", end_time: \"2017-07-01T00:00:00Z\"){average_humidity average_pressure average_temperature}}",
  "database": "syncmesh",
  "collection": "sensor_data",
  "request_type": "aggregate"
}

The result will look like this:

{
  "average_humidity": 48.17521146522349,
  "average_temperature": 25.425487457020832,
  "average_pressure": 94973.26202117185
}

Mutations

With syncmesh, it is also possible to create, modify existing, or delete sensor data entries.

Insert data

You can insert your own data like this:

{
  "query": "mutation{addSensors(sensors: [{pressure: 1, temperature: 2, humidity: 23, lat: 23.123, lon: 23.232, timestamp: \"2017-06-26T00:00:00Z\"}])}",
  "database": "syncmesh",
  "collection": "sensor_data"
}

Notice that the sensors parameter is a list, so you can insert multiple documents at once. For the structure of a sensor, look into the wiki page "Database structure". The mutation will return the object IDs of the created documents.

Modify data

An update operation is similar to create, but with only one document at once and a specified _id:

{
  "query": "mutation{update(_id: \"1\", sensor: {pressure: 1, temperature: 2, humidity: 23, lat: 23.123, lon: 23.232, timestamp: \"2017-06-26T00:00:00Z\"}){temperature}}",
  "database": "syncmesh",
  "collection": "sensor_data"
}

Depending on what you specify as the return parameters (in the example above, it is temperature), the return object of the query will contain this value before the update. so if you changed the temperature from 23 to 99, the return will contain "temperature": 23.

Delete data

Here's how you delete an entry. You only need to specify the document ID and some return param, as a requirement by GraphQL:

{
  "query": "mutation{deleteSensor(_id: \"60e0666c6f1faa4d3821e3a0\"){temperature}}",
  "database": "syncmesh",
  "collection": "sensor_data"
}

You can also delete sensors in a time range. Both the start time and end time are required parameters in this case:

{
  "query": "mutation{deleteInTimeRange(start_time: \"2017-06-26T00:00:00Z\", end_time: \"2017-07-02T00:00:00Z\")}",
  "database": "syncmesh",
  "collection": "sensor_data"
}

This mutation returns the number of deleted documents, for example "deleteInTimeRange": 3.

Other queries

Document estimate

You can get a (good) fast estimate of how many documents are in your collection by using:

{
  "query": "{docEstimate}",
  "request_type": "collect"
}

Self Deploying Functions

  {
    "query": "{sensors(start_time: \"2017-07-30T00:00:00Z\", end_time: \"2017-07-31T00:00:00Z\"){temperature humidity timestamp}}",
    "database": "syncmesh",
    "collection": "sensor_data",
    "request_type": "collect",
    "external_functions_name": ["echoit"],
    "deploy_function_image": "ghcr.io/openfaas/alpine:latest",
    "password": "lxw92pNSyKfHJAAx7vezLzkLnwkA9eqyMM58TRMF1CIyMN36YuDGkJwfvqhqln8"
  },