-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
JSON streaming array updates #18
Comments
@pljakobs In your comment #17 (comment) you suggest using schema annotations to identify index fields. This seems similar to defining indices in a transactional database system, so is a sensible suggestion. It also suggests that ConfigDB would be responsible for enforcing indexing integrity. Implementing all that is a fair bit of work. If I understand correctly, the purpose would be to enable updates like this: {
"general": {
"channels[\"13\"]": {
"name": "blue"
}
}
} Using the selector approach we'd do this: {
"general": {
"channels[pin=13]": {
"name": "blue"
}
}
} Which is more descriptive and simpler to implement. You could also do this: {
"general": {
"channels[name=red]": {
"pin": 25,
"name": "green"
}
}
} Or whatever. Would that work for you? If so, I'll go ahead and implement it. |
I'm perfectly happy with the selectors as you describe them. After all, it's reasonable to expect the application to have the dataset, too, and to know what it "wants" to update. btw, without a selector, the default operation would be to append, I assume? I believe that, to be really true to arrays, at some point an "update by Index" or even an "insert before index" might be desireable (after all, an array implies some sort of order, just by the fact that it can be accessed by index) but for now, the front-end can get around this if it just manipulates the array locally and overwrites it in ConfigDB |
Any effort spent here is better than time spent later fixing/updating lots of application code if the API changes! So this is one of those things that needs a minimal, simple implementation to make the library useable.
No, overwrite - see the opening post. I'll edit that to clarify the use-cases. |
well, let me rephrase then: for my use case, the selector approach is perfectly suitable.
ah yes, stupid me, forgot that. |
I've updated the head comment. Below is the python script I used to generate the test cases. I'll use that as a basis for the library tests. '''Script to verify appropriate array selector expressions
'''
TEST_CASES = {
'Overwrite array': [
'x = [1, 2, 3, 4]',
'x[0:] = [8, 9]',
],
'Clear array': [
'x = []',
],
'Update single item': [
'x[0] = 8',
'x[2] = 8',
'x[-1] = 8',
'x[4] = 8',
],
'Update multiple items': [
'x[0:2] = [8, 9]',
'x[1:1] = [8, 9]',
'x[1:2] = [8, 9]',
'x[2:] = [8, 9]',
'x[0:1] = 8',
'x[pin] = 8',
],
'Insert item': [
'x[3:0] = [8]',
'x[3:3] = [8]',
'x[-1:] = [8, 9]',
],
'Append items (insert at end)': [
'x[] = [8, 9]',
'x[10:] = [8, 9]',
'x[10:] = 8',
]
}
for title, expressions in TEST_CASES.items():
print(title)
for expr in expressions:
try:
vars = {'x': [1, 2, 3, 4]}
exec(expr, None, vars)
x = vars['x']
except Exception as e:
x = e
a, _, b = expr.partition(' = ')
a = f'"{a}"'
print(f' {a:12s}: {b:16s} {x}') |
Re-ordering is an interesting case. A thought here. If we have an array: {
"animals": ["rabbit", "fox", "donkey", "cat"]
} And want to move {
"animals": ["rabbit", "cat", "fox", "donkey"]
} We could define an ordering operation {
"animals[*]": [0, 3, 1, 2]
} We could come up with more concise operations, like: {
"animals[*1:2]": [2]
} With the It's not very natural language though so something to chew over. |
Implement array selectors as discussed in #18. Also update `import` methods to return `Status` which explains source of any error. * Add array test cases * Implement indexed selectors * Add named key assignment * Add `clearDirty` call and use in tests. Avoids un-necessarily flushing changes to storage * Return `Status` from import methods * Add FormatError codes
This PR extends the `Database::createExportStream` method to support basic path selection, for example `http://192.168.13.10/color.brightness`. Array item selection isn't included, but could be added in a similar way for updates as discussed in #18.
Current streaming update (writing) behaviour is to overwrite only those values received.
This allows selective updating of properties. For example:
This updates one value in the database, leaving everything else unchanged.
Arrays are overwritten entirely:
replaces everything in general.supported_color_models, and this::
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:
[]
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
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 requirex[len(x):]
orx[10000000:0]
, for example.The following operations assume an initial value of
x = [1, 2, 3, 4]
Update Object array item by value
This is an invention (I think) so we can select items by field.
or
Note: We could support simple arrays like this:
So 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.
The text was updated successfully, but these errors were encountered: