Using jsonPath looking for a string - jsonpath

I'm trying to use jsonPath and the pick function to determine if a rule needs to run or not based on the current domain. A simplified version of what I'm doing is here:
global
{
dataset shopscotchMerchants <- "https://s3.amazonaws.com/app-files/dev/merchantJson.json" cachable for 2 seconds
}
rule checkdataset is active
{
select when pageview ".*" setting ()
pre
{
merchantData = shopscotchMerchants.pick("$.merchants[?(#.merchant=='Telefora')]");
}
emit
<|
console.log(merchantData);
|>
}
The console output I expect is the telefora object, instead I get all three objects from the json file.
If instead of merchant=='Telefora' I use merchantID==16 then it works great. I thought jsonPath could do matches to strings as well. Although the example above isn't searching against the merchantDomain part of the json, I'm experiencing the same problem with that.

Your problem comes from the fact that, as stated in the documentation, the string equality operators are eq, neq, and like. == is only for numbers. In your case, you want to test if one string is equal to another string, which is the job of the eq string equality operator.
Simply swap == for eq in you JSONpath filter expression and you will be good to go:
global
{
dataset shopscotchMerchants <- "https://s3.amazonaws.com/app-files/dev/merchantJson.json" cachable for 2 seconds
}
rule checkdataset is active
{
select when pageview ".*" setting ()
pre
{
merchantData = shopscotchMerchants.pick("$.merchants[?(#.merchant eq 'Telefora')]"); // replace == with eq
}
emit
<|
console.log(merchantData);
|>
}
I put this to the test in my own test ruleset, the source for which is below:
ruleset a369x175 {
meta {
name "test-json-filtering"
description <<
>>
author "AKO"
logging on
}
dispatch {
domain "exampley.com"
}
global {
dataset merchant_dataset <- "https://s3.amazonaws.com/app-files/dev/merchantJson.json" cachable for 2 seconds
}
rule filter_some_delicous_json {
select when pageview "exampley.com"
pre {
merchant_data = merchant_dataset.pick("$.merchants[?(#.merchant eq 'Telefora')]");
}
{
emit <|
try { console.log(merchant_data); } catch(e) { }
|>;
}
}
}

Related

Need to compare array in Marklogic with xquery

I need to compare array in MarkLogic with Xquery .
Query parameters:
{
"list": {
"bookNo": 13,
"BookArray":[20,21,22,23,24,25]
}
}
Sample Data:
{
"no":01'
"arrayList"[20,25]
}
{
"no":02'
"arrayList"[20,27]
}
{
"no":03'
"arrayList"[20,23,25]
}
Output:
"no":01
"no":03
I need to return "no" where all values from arraylist should be match with bookArray.
Ok. You do not explain if the actual data is in the system or not. So I did an example as if it is all in memory.
I chose to keep the sample in the MarkLogic JSON representation which has some oddities like number-nodes and array-nodes under the hood. To make it more readable if you dig into it, i used fn:data() to get less verbose. In all reality, if this was an in-memory operation and I could not use Javascript, then I would have converted the JSON structures to maps.
Here is a sample to help you explore. I cleaned up the JSON to be valid and for my sample wrapped the three samples in a single array.
xquery version "1.0-ml";
let $param-as-json := xdmp:unquote('{
"list": {
"bookNo": 13,
"BookArray":[20,21,22,23,24,25]
}
}')
let $list-as-json := xdmp:unquote('[
{
"no":"01",
"arrayList":[20,25]
},
{
"no":"02",
"arrayList":[20,27]
},
{
"no":"03",
"arrayList":[20,23,25]
}
]')
let $my-list := fn:data($param-as-json//BookArray)
return for $item in $list-as-json/*
let $local-list := fn:data($item//arrayList)
let $intersection := fn:data($item//arrayList)[.=$my-list]
where fn:deep-equal($intersection, $local-list)
return $item/no
Result:
01
03

Sort document by integer Firestore Kotlin

I want to sort documents by img in descending order.
I've tried to add indexes in firebase console. Here is a screenshot from indexes tab:
Here is my database structure:
Here is my code:
db.collection("images").whereEqualTo("user", uid).orderBy("img", Query.Direction.DESCENDING).get()
.addOnSuccessListener {
if (it.isEmpty) {
Log.i("Image", "Sorry, no image")
} else {
for (task in it) {
Log.i("Image", task.get("img").toString())
}
}
}
And here is log:
I/Image: 2
I/Image: 1
I/Image: 3
I/Image: 4
I/Image: 6
I/Image: 7
What am I doing wrong?
Notice that as stated on the documentation there could be two explanations behind the behavior you are experiencing:
If you have a filter with a range comparison (<, <=, >, >=), your first ordering must be on the same field
You cannot order your query by any field included in an equality (=) or in clause.
Based on the following snippet provided on the documentation:
citiesRef.whereGreaterThan("population", 100000).orderBy("population").limit(2)
You could try the following (but I'm not sure if it'll work because of 2.):
db.collection("images").whereEqualTo("user", uid).orderBy("user").orderBy("img", Query.Direction.DESCENDING).get()
.addOnSuccessListener {
if (it.isEmpty) {
Log.i("Image", "Sorry, no image")
} else {
for (task in it) {
Log.i("Image", task.get("img").toString())
}
}
}

Trying to force an entry in an array to be an array

I am trying to create an associative array of associative arrays in gawk, and what I initially tried was:
options[key][subkey] = 1
However, when it got to this line, I unceremoniously received the error fatal: attempt to use scalar 'option["Declaration"]' as an array ("Declaration" being one of the main keys that my program uses, although I presume the exact value is irrelevant. At this particular point in the program, there was no "Declaration" entry assigned, although there were entries which had "Declaration" as a subkey on other entries, which may be meaningful).
So with a bit of googling, I found another stackoverflow question that looked like it answered my issue, so I put the following code immediately above it:
if (typeof(options[key])!="array") {
options[key] = 0;
delete options[key];
split("",options[key]);
}
However, this does not work either, instead now giving me the error: fatal: split: second argument is not an array
What am I doing wrong?
EDIT: Note, that I cannot use a basic 2-dimensional array here... for what I am doing, it is important that I am using one associative array to another because I need to be able to later identify the subkeys that were used on a given key.
Pursuant to requests below, I am posting the relevant functions that use the associative array, which may help clarify what is going on.
function add_concrete(key, concrete) {
if (key == concrete) {
return;
}
if (length(options[key])>0) {
for(i in options[key]) {
add_concrete(i, concrete);
}
}
contains[key][concrete] = 1
}
function add_options(name, value) {
subkey = trim(name);
if (subkey == "") {
return;
}
if (match(value, ";") > 0) {
exporting = 0;
}
split(value, args, /[ |;]*/);
for (i in args) {
key = trim(args[i]);
if (key != "") {
print("Adding " name " to " key);
options[key][subkey] = 1
if (concrete[key]) {
add_concrete(subkey, key);
}
}
}
}
Sorry, cooking at the same time. As you didn't post much, don't have much to work with, but with no "initialization":
$ awk 'BEGIN {
options[key] = 0;
delete options[key];
# options[key][1] # cant see me
split("",options[key]);
}'
awk: cmd. line:5: fatal: split: second argument is not an array
But with "initialization":
$ awk 'BEGIN {
options[key] = 0;
delete options[key];
options[key][1] # can see me
split("",options[key]);
}'
$_ # see this cursor happily blinking without any error

assigning value in razor difficulty

I am having the following pice of code which is firing error
Error 1 Invalid expression term '='
#{
int Interest;
}
<td>#if (#item.interest.HasValue)
{
#Interest= #item.interest.Value.ToString("F2");
}
When declaring a variable, this variable needs to be assigned:
#{
string Interest = "";
}
and then:
#if (item.interest.HasValue)
{
Interest = item.interest.Value.ToString("F2");
}
This being said doing something like this in a view is a very bad design. I mean things like declaring and assigning variables based on some condition is not a logic that should be placed in a view. The view is there to display data. This logic should go to your controller or view model.
Inside your #if block you can address variables without the # sign.
#if (#item.interest.value) {
#item= #item.interest.Value
}
Is interpreted as:
#if (#item.interest.value) {
Write(item=);
Write(#item.interest.Value);
}
As you can see Write(item=) is not valid C# code.
You should use:
#if (item.interest.value) {
item = item.interest....
}
The reason your if (#item....) statement compiles, with the # sign. Is because you can prefix an identifier with the # to use reserved words as identifier names.
Try this:
#{
string Interest;
}
<td>#if (#item.interest.HasValue)
{
Interest= #item.interest.Value.ToString("F2");
}
By the way you are trying to assign a string (the result of ToString()) to an integer. This will not work.

Is there a version of the removeElement function in Go for the vector package like Java has in its Vector class?

I am porting over some Java code into Google's Go language and I converting all code except I am stuck on just one part after an amazingly smooth port. My Go code looks like this and the section I am talking about is commented out:
func main() {
var puzzleHistory * vector.Vector;
puzzleHistory = vector.New(0);
var puzzle PegPuzzle;
puzzle.InitPegPuzzle(3,2);
puzzleHistory.Push(puzzle);
var copyPuzzle PegPuzzle;
var currentPuzzle PegPuzzle;
currentPuzzle = puzzleHistory.At(0).(PegPuzzle);
isDone := false;
for !isDone {
currentPuzzle = puzzleHistory.At(0).(PegPuzzle);
currentPuzzle.findAllValidMoves();
for i := 0; i < currentPuzzle.validMoves.Len(); i++ {
copyPuzzle.NewPegPuzzle(currentPuzzle.holes, currentPuzzle.movesAlreadyDone);
copyPuzzle.doMove(currentPuzzle.validMoves.At(i).(Move));
// There is no function in Go's Vector that will remove an element like Java's Vector
//puzzleHistory.removeElement(currentPuzzle);
copyPuzzle.findAllValidMoves();
if copyPuzzle.validMoves.Len() != 0 {
puzzleHistory.Push(copyPuzzle);
}
if copyPuzzle.isSolutionPuzzle() {
fmt.Printf("Puzzle Solved");
copyPuzzle.show();
isDone = true;
}
}
}
}
If there is no version available, which I believe there isn't ... does anyone know how I would go about implementing such a thing on my own?
How about Vector.Delete( i ) ?
Right now Go doesn't support generic equality operators. So you'll have to write something that iterates over the vector and removes the correct one.

Resources