-
Notifications
You must be signed in to change notification settings - Fork 1
Description
Current streaming update (writing) behaviour is to overwrite only those values received.
This allows selective updating of properties. For example:
{
"security": {
"api_secured": "false"
}
}This updates one value in the database, leaving everything else unchanged.
Arrays are overwritten entirely:
{
"general": {
"supported_color_models": [
"RGB",
"RAW"
]
}
}replaces everything in general.supported_color_models, and this::
{
"general": {
"channels": [
{
"pin": 1,
"name": "dummy"
}
]
}
}Deletes all existing entries in general.channels and replaces it with the one object provided.
As mentioned in the discussion #17, this is really the simplest way to handle updates, but does not allow updating of individual array items. This is desirable so that update messages do not have to contain data which doesn't change.
Possible modes of update operation may include:
- Overwrite, as above - this includes clearing/deleting the entire array by setting it to
[] - Wipe everything and replace with provided JSON data
- Overwrite an array item at a given position
- Insert an array item at a given position
- Delete an array item
- Overwrite a property or properties of an object in an object array
This is basically XPath, JSONPath, whatever, so a selector expression is used to identify the item to update.
Given that this is focused on configuration data, the dataset is not going to be particularly large.
The benefits of providing an elaborate query language in a resource-limited device is interesting, but of doubtful value for this application.
Proposed solution
A simple selector mechanism could be implemented by modifying JSON key values.
For simplicity I'll use an array of integers for demonstration.
Overwrite array
"x": [1, 2, 3, 4]Clear array
"x": []Note: The array itself cannot be deleted as it's fixed by the schema.
Indexed operations
Python list operations provide a good working model for this.
So x[i] corresponds to a single element at index i, x[i:j] is a 'slice' starting at index i and ending with index (j-1).
Note that x[] = [8, 9] isn't valid python but we can support it as shorthand for 'append'. Python would require x[len(x):] or x[10000000:0], for example.
The following operations assume an initial value of x = [1, 2, 3, 4]
Overwrite array
"x" : [1, 2, 3, 4] [1, 2, 3, 4]
"x[0:]" : [8, 9] [8, 9]
Clear array
"x" : [] []
Update single item
"x[0]" : 8 [8, 2, 3, 4]
"x[2]" : 8 [1, 2, 8, 4]
"x[-1]" : 8 [1, 2, 3, 8]
"x[4]" : 8 list assignment index out of range
Update multiple items
"x[0:2]" : [8, 9] [8, 9, 3, 4]
"x[1:1]" : [8, 9] [1, 8, 9, 2, 3, 4]
"x[1:2]" : [8, 9] [1, 8, 9, 3, 4]
"x[2:]" : [8, 9] [1, 2, 8, 9]
"x[0:1]" : 8 can only assign an iterable
"x[pin]" : 8 name 'pin' is not defined
Insert item
"x[3:0]" : [8] [1, 2, 3, 8, 4]
"x[3:3]" : [8] [1, 2, 3, 8, 4]
"x[-1:]" : [8, 9] [1, 2, 3, 8, 9]
Append items (insert at end)
"x[]" : [8, 9] invalid syntax (<string>, line 1)
"x[10:]" : [8, 9] [1, 2, 3, 4, 8, 9]
"x[10:]" : 8 can only assign an iterableUpdate Object array item by value
This is an invention (I think) so we can select items by field.
"channels[name=dummy]": {
"pin": 1
}or
"channels[pin=1]": {
"name": "new name"
}Note: We could support simple arrays like this:
"x[=1]": 5So if x is [3, 1, 4, 1] it would be updated to [3, 5, 4, 5].
Not sure there's a particular use-case for this so might leave it.