How to go to parent operator in JSONPath? - jsonpath

According to this, there is no equivalent syntax for this?
Is there anyway to achieve this?
Example
{ ...
attrib1: {},
attrib2: []
...
}
When I'm looping in attrib2 path, i would like to get some info from attrib1. How would i do it in this case?

Related

JSONPath - Filter expression to print a field if an array contains a string

I have the following JSON and am trying to write a JSON Path expression which will return me the isbn number when I have a id of either '123456789' or '987654321'. I tried the following but this did not work. Can anybody tell me what I am doing wrong please. Thanks in advance
JSON Path Expression
$.books[?(#.ids== '123456789' )].isbnNumber
JSON
{
"books": [{
"title": "10",
"isbnNumber": "621197725636",
"ids": [
"123456789",
"987654321"
]
}]
}
The (more traditional) JSONPath implementations that stick close(r) to Goessner's reference specification do not offer handy functions like in which are available in extended implementations like JayWay's JSONPath.
Using Gatling's JSONPath, one thing we could do if the positions of the Ids in question are fixed is accessing their respective indices directly to make the comparison:
$.books[?(#.ids[0] == "123456789" || #.ids[1] == "987654321")].isbnNumber
This will give you the desired result of your example; however, some books only have one of the two indices, or they Id to compare to shows up on a different position it won't work.

Add element to arrays, that are values to a given key name (json transformation with jq)

I'm a jq newbie, and I try to transform a json (a Swagger spec). I want to add an element to the array value of the "parameter" keys:
{
...
"paths": {
"/great/endpoint1": {
"get": {
"parameters": [] <<--- add a value here
}
}
"/great/endpoint2": {
"post": {
"parameters": [] <<-- and here too here too etc.
....
The following jqplay almost works. It adds values to the right arrays, but it has the nasty side effect of also removing the "x-id" value from the root of the input json. It's probably because of a faulty if-condition. As the paths contain a varying string (the endpoint names), I don't know how to write a wildcard path expression to address those, which is why I have tried using walk instead:
https://jqplay.org/s/az56quLZa3
Since the sample data is incomplete, it's difficult to say exactly what you're looking for but it looks like you should be using parameters in the call to walk:
walk(if type=="object" and has("parameters")
then .parameters += [{"extra": "value"}]
else . end)
If you want to restrict the walk to the top-level paths, you would preface the above with: .paths |=

Is it possible to combine if_not_exists and list_append in update_item

I'm trying to use the update_item functionality for DynamoDB in boto3.
I'm struggling right now to update lists for items. I would like to create a new list if the list does not exist yet and otherwise append to the existing list.
Using an UpdateExpression of the form SET my_list = list_append(my_list, :my_value) returns an error "The provided expression refers to an attribute that does not exist in the item" if the list does not exist yet.
Any idea how I would have to modify my UpdateExpression?
You can use list_append(if_not_exists()) construction.
UpdateExpression:
'SET my_list2 = list_append(if_not_exists(my_list2, :empty_list), :my_value)'
ExpressionAttributeValues:
{ ":my_value":{"L": [{"S":"test"}]}, ":empty_list":{"L":[]} }
Update: as mentioned in the comments, boto3 now raises an error for the expression above and a version without explicit types works: { ":my_value": ["test"], ":empty_list":[] }.
An alternative to Boris solution could be to use set instead of list datatype and use the ADD keyword, it does exactly what you want.
With Add, the update expression becomes: ADD setName :s
And the expression attribute values can be like: {":s": {"SS":["First", "Second"]}}
http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.UpdateExpressions.html#Expressions.UpdateExpressions.ADD

Gremlin.compile() cannot execute query that works in gremlin console

When I execute the following in a gremlin console I get the expected result.
g.V('name', 'a').next().query().has('b', GREATER_THAN_EQUAL, 100).orderBy('timestamp', Order.DESC).edges()
Now I am trying to execute the same from Java (following this guide) however I cannot get it to work.
I've tried this
Pipe pipe = Gremlin.compile("_().query().has('b', GREATER_THAN_EQUAL, 100).orderBy('timestamp', Order.DESC).edges()");
pipe.setStarts(new SingleIterator<Vertex>(graph.getVertices("name", 'a').iterator().next()));
for(Object name : pipe) {
}
javax.script.ScriptException: javax.script.ScriptException:
groovy.lang.MissingMethodException: No signature of method:
com.tinkerpop.gremlin.groovy.GremlinGroovyPipeline.query() is
applicable for argument types: () values: [] Possible solutions:
every(), every(groovy.lang.Closure), grep(),
tree([Lcom.tinkerpop.pipes.PipeFunction;),
tree([Lgroovy.lang.Closure;),
tree(com.tinkerpop.pipes.util.structures.Tree)
And this
Pipe pipe = Gremlin.compile("_().next().query().has('b', GREATER_THAN_EQUAL, 100).orderBy('timestamp', Order.DESC).edges()");
pipe.setStarts(new SingleIterator<Vertex>(graph.getVertices("name", 'a').iterator().next()));
for(Object name : pipe) {
}
javax.script.ScriptException: javax.script.ScriptException:
groovy.lang.MissingMethodException: No signature of method:
com.tinkerpop.gremlin.groovy.jsr223.GremlinGroovyScriptEngine.query()
is applicable for argument types: () values: [] Possible solutions:
every(), every(groovy.lang.Closure), grep(), grep(java.lang.Object),
any(), dump()
Any ideas?
This line looks suspicious to me:
Pipe pipe = Gremlin.compile("_().next().query().has('b', GREATER_THAN_EQUAL, 100).orderBy('timestamp', Order.DESC).edges()");
You are trying to compile a Pipe out of something that doesn't evaluate to a Pipeline. In other words, you start with the identity pipe (_()) but then you next() it out and drop down into a vertex query which returns edges() edges() returns a Iterator and not a Pipeline. If you look at the example of Gremlin.compile the evaluated code of the Gremlin string returns a pipeline.
Pipe pipe = Gremlin.compile("_().out('knows').name");
My guess is that if you instead changed your code to something like (untested):
Pipe pipe = Gremlin.compile("_().outE.has('b', GREATER_THAN_EQUAL, 100).order{it.b.timestamp <=> it.a.timestamp}");
pipe.setStarts(new SingleIterator<Vertex>(graph.getVertices("name", 'a').iterator().next()));
for(Object name : pipe) {
}
you might have some success. I suppose that if that worked, then you would want to figure out how to re-optimize your query as I guess that some backends could take optimize the orderBy of the Vertex query, whereas the order Gremlin step is just an in-memory sort.
Okay so I have decided to use GremlinGroovyScriptEngine instead of Gremlin.compile(). This approach is also described on the same guide and I actually prefer this because it gives me parameterisation and I don't need to modify the original query (replace g. with _()).
ScriptEngine engine = new GremlinGroovyScriptEngine();
Bindings bindings = engine.createBindings();
bindings.put("g", graph);
bindings.put("value", 100);
bindings.put("DESC", Order.DESC);
engine.eval("g.V('name', 'a').next().query().has('b', Compare.GREATER_THAN_EQUAL, value).orderBy('timestamp', DESC).edges()", bindings);
I would still be interested in knowing why Gremlin.compile did not work, hopefully the above will be helpful to someone else.

What is the proper idiomatic way of checking if a map has no elements in coffeescript?

since a code example is worth a thousand words:
console.log(#searchEnginesMap, {}, #searchEnginesMap == {}, #searchEnginesMap is {}, #searchEnginesMap.empty?, #searchEnginesMap.length)
returns:
{} {} false false false undefined
what's the correct syntax to get a true value for this? (or how should I correctly check if I have a map with zero elements?)
EDIT: extra credit:
how do you compare these two dictionaries to have them be the same (by value, not be reference):
a = {"foo":"bar?q=%s","baz":"qux?q=%s"}
b = {"foo":"bar?q=%s","baz":"qux?q=%s"}
so I need to know what I can use to get get true while comparing these?
Thanks in advance.
There is no CoffeeScript magic solution here. If you want to know if an Object is empty then you have to count the keys. You could use Object.keys:
if Object.keys(obj).length == 0
# obj is empty
Or you could use a loop:
if (true for v of obj).length == 0
# obj is empty
The for ... of loop version could be wrapped in a short-circuiting function without much effort.
I would probably wimp out and grab Underscore or Lodash so that I could use _.isEmpty:
if _(obj).isEmpty()
# obj is empty
That would also solve your second problem because you'd get _.isEqual too:
_(foo: "bar?q=%s", baz: "qux?q=%s").isEqual(baz: "qux?q=%s", foo: "bar?q=%s")
# true
Underscore demo: http://jsfiddle.net/ambiguous/Jad6e/

Resources