Given these lines of code:
let order = cts.indexOrder(cts.elementReference(fn.QName('','order')))
cts.search(cts.jsonPropertyValueQuery('order','*', ['wildcarded'] ),order)
I get this result:
{"order":["a", "m"]}
{"order":"a"}
{"order":["a", "x"]}
{"order":"j"}
{"order":["j", "k", "l"]}
{"order":["j", "k"]}
{"order":["j", "k", "m"]}
{"order":"m"}
{"order":["m", "z"]}
Shouldn't ["a"] sort before ["a","m"], and ["j","k"] precede ["j","k","l"]?
It seems like there is some kind of ordering, but it's not precise in this way, and I'd like to understand the rules, as we have exactly this situation in a project I'm working on.
Related
i have conditions in my elasticsearch documents, for example:
{
...
"conditions": [
{
"required": ["a"],
"prohibited": ["f"]
},
{
"required": ["a", "b"],
"prohibited": ["c", "d"]
}
]
}
And a have a dataset, for example ["a", "b", "f"] (a true example, because second condition matches)
Now I want to write a Elasticsearch-Query that returns all documents to which the conditions apply to my dataset. The tricky part which i am hanging on is not to loose the single conditions relations. All entries in required have to match in combindation and with prohibited it's the same.
Hope there is a es-specialist who can give me an approach what the best way is to solve this challenge. At the moment i think on a Script-Query or different structure of these conditions in our documents. But maybe there is a way (which i don't see) to formulate this as normal ES-Query.
After a lot of tries and frustration i decided to solve my problem with a painless script. It's not perfect from a performance point of view but it works.
Q: How do I prevent JSONata from "auto-flattening" arrays in an array constructor?
Given JSON data:
{
"w" : true,
"x":["a", "b"],
"y":[1, 2, 3],
"z": 9
}
the JSONata query seems to select 4 values:
[$.w, $.x, $.y, $.z]
The nested arrays at $.x and $.y are getting flattened/inlined into my outer wrapper, resulting in more than 4 values:
[ true, "a", "b", 1, 2, 3, 9 ]
The results I would like to achieve are
[ true, ["a", "b"], [1, 2, 3], 9 ]
I can achieve this by using
[$.w, [$.x], [$.y], $.z]
But this requires me to know a priori that $.x and $.y are arrays.
I would like to select 4 values and have the resulting array contain exactly 4 values, independent of the types of values that are selected.
There are clearly some things about the interactions between JSONata sequences and arrays that I can't get my head around.
In common with XPath/XQuery sequences, it will flatten the results of a path expression into the output array. It is possible to avoid this in your example by using the $each higher-order function to iterate over an object's key/value pairs. The following expression will get what you want without any flattening of results:
$each($, function($v) {
$v
})
This just returns the value for each property in the object.
UPDATE: Extending this answer for your updated question:
I think this is related to a previous github question on how to combine several independent queries into the same question. This uses an object to hold all the queries in a similar manner to the one you arrived at. Perhaps a slightly clearer expression would be this:
{
"1": t,
"2": u.i,
"3": u.j,
"4": u.k,
"5": u.l,
"6": v
} ~> $each(λ($v){$v})
The λ is just a shorthand for function, if you can find it on your keyboard (F12 in the JSONata Exerciser).
I am struggling to rephrase my question in such as way as to describe the difficulties I am having with JSONata's sequence-like treatment of arrays.
I need to run several queries to extract several values from the same JSON tree. I would like to construct one JSONata query expression which extracts n data items (or runs n subqueries) and returns exactly n values in an ordered array.
This example seems to query request 6 values, but because of array flattening the result array does not have 6 values.
This example explicitly wraps each query in an array constructor so that the result has 6 values. However, the values which are not arrays are wrapped in an extraneous & undesirable array. In addition one cannot determine what the original type was ...
This example shows the result that I am trying to accomplish ... I asked for 6 things and I got 6 values back. However, I must know the datatypes of the values I am fetching and explicitly wrap the arrays in an array constructor to work-around the sequence flattening.
This example shows what I want. I queried 6 things and got back 6 answers without knowing the datatypes. But I have to introduce an object as a temporary container in order to work around the array flattening behavior.
I have not found any predicates that allow me to test the type of a value in a query ... which might have let me use the ?: operator to dynamically decide whether or not to wrap arrays in an array constructor. e.g. $isArray($.foo) ? [$.foo] : $.foo
Q: Is there an easier way for me to (effectively) submit 6 "path" queries and get back 6 values in an ordered array without knowing the data types of the values I am querying?
Building on the example from Acoleman, here is a way to pass in n "query" strings (that represent paths):
(['t', 'u.i', 'u.j', 'u.k', 'u.l', 'v'] {
$: $eval('$$.' & $)
}).$each(function($o) {$o})
and get back an array ofn results with their original data format:
[
12345,
[
"i",
"ii",
"iii"
],
[],
"K",
{
"L": "LL"
},
null
]
It seems that using $each is the only way to avoid any flattening...
Granted, probably not the most efficient of expressions, since each has to be evaluated from a path string starting at the root of the data structure -- but there ya go.
This is a predicate that is supposed to write backwards out of a list, but since 'tab(-2)' doesn't work I was wondering if there are other predicates, or a different way of using'tab/1' in order to move backwards.
(Using 'reverse/2' is not an option in this case).
Im fairly new to all this, so I hope I did everything right, any kind of help would be appreciated.
snakeprint([X|Xs],Counter1,Counter2,Y,2):-
tab((Y*3)-3),
write(X),
tab(-2),
C1 is Counter1-1,
snakeshift([X|Xs],V),
snakeprint(V,C1,Counter2,Y,2).
snakeprint([H|T]) :-
snakeprint(T),
write(H).
snakeprint([]).
Input: ["M", "a", "r", "y", " ", "h", "a", "d"]
Output: dah yraM
I have datasets that consist of arrays and single values
{
"a": "18",
"b": ["x","y","z"]
}
or arrays and arrays
{
"a": ["g", "h", "i"],
"b": ["x", "y", "z"]
}
and i plan to map out each combination (like "18-x", "18-y", "18-z" or "g-x", "g-y"...) to count these afterwards (or do anything else). I'm used to CouchDB with their emit function: I simply emitted multiple combinations per document. How is this supposed to be done in RethinkDB?
Note: The datasets are produced by a join
I would recommend making both fields always be arrays, even if the arrays sometimes only have a single value.
If you do that, you can do this with concat_map:
row('a').concatMap(function(a){
return row('b').map(function(b){
return a.add('-').add(b);
});
});
If you want to continue using a mix of single values and arrays, you can do that by replacing r.row('a') with r.branch(r.row('a').typeOf().eq('ARRAY'), r.row('a'), [r.row('a')]).
I am having a basic issue here with linq . Though this can be solved with repeated loops . I am trying to know how can this be done in linq .
I have two lists .
List<string> a = new List<string>{"a","b","c","d","e","f"};
List<string> b = new List<string> { "a", "b", "c", "x", "y", "z" };
I want to compare with list a and whichever element in b is found in a . I want to remove that element from b . In other words I want to remove {"a","b","c"} from b based on comparison from list a and want to contain only {"x","y","z"} in list b . Is there a single statement linq to solve this ?
(I'm sure this is a duplicate of another post just a few days ago, but I can't find it...)
If you need a modification in place, you can use List<T>.RemoveAll:
b.RemoveAll(x => a.Contains(x));
Or more efficiently (if the lists are large):
HashSet<string> set = new HashSet<string>(a);
b.RemoveAll(set.Contains);
Note that modifying a collection in place isn't idiomatic in LINQ, which is why the above uses the .NET 2 list-specific method.
Or if you're happy to change b to refer to a new list instead, then you can use LINQ:
b = b.Except(a).ToList();