I'm building a json query to pass to a mongodb database in R.
In one scenario, I have a vector of dates and I want to query the database to return all records which have a date in the relevant field that matches a date in my vector of dates.
The second scenario is the same as the first, but this time I have a vector of character strings (IDs) and need to return all the records with matching IDs.
I understood the correct way to do this in a json query is to use the $in operator, and then put my vector in an array.
However, when I pass the query to my mongodb database, the exportLogId returns NULL. I'm quite sure that the problem is something to do with how I am representing the $in operator in the final query, since I have very similarly structured queries without the $in operator and they are all working. If I look for just one of my target dates or character strings, I get the desired result.
I followed the mongodb manual here to construct my query, and the only issue I can see is that the $in operator in the output of jsonlite::toJSON() is enclosed in double quotes; whereas I think it might need to be in single quotes (or no quotes at all, but I don't know how to write the syntax for that).
I'm creating my query in two steps:
Create the query as a series of nested lists
Convert the list object to json with jsonlite::toJSON()
Here is my code:
# Load libraries:
library(jsonlite)
# Create list of example dates to query in mongodb format:
sampledates <- c("2022-08-11T00:00:00.000Z",
"2022-08-15T00:00:00.000Z",
"2022-08-16T00:00:00.000Z",
"2022-08-17T00:00:00.000Z",
"2022-08-19T00:00:00.000Z")
# Create query as a list object:
query_list_l <- list(filter =
# Add where clause:
list(where =
# Filter results by list of sample dates:
list(dateSampleTaken = list('$in' = sampledates),
# Define format of column names and values:
useDbColumns = "true",
dontTranslateValues = "true",
jsonReplaceUndefinedWithNull = "true"),
# Define columns to return:
fields = c("id",
"updatedAt",
"person.visualId",
"labName",
"sampleIdentifier",
"dateSampleTaken",
"sequence.hasSequence")))
# Convert list object to JSON:
query_json = jsonlite::toJSON(x = query_list_l,
pretty = TRUE,
auto_unbox = TRUE)
The JSON query now looks like this:
> query_json
{
"filter": {
"where": {
"dateSampleTaken": {
"$in": ["2022-08-11T00:00:00.000Z", "2022-08-15T00:00:00.000Z", "2022-08-16T00:00:00.000Z", "2022-08-17T00:00:00.000Z", "2022-08-19T00:00:00.000Z"]
},
"useDbColumns": "true",
"dontTranslateValues": "true",
"jsonReplaceUndefinedWithNull": "true"
},
"fields": ["id", "updatedAt", "person.visualId", "labName", "sampleIdentifier", "dateSampleTaken", "sequence.hasSequence"]
}
}
As you can see, $in is now enclosed in double quotes, even though I put it in single quotes when I created the query as a list object. I have tried replacing with sprintf() but that just adds a lot of backslashes to my query. I also tried:
query_fixed <- gsub(pattern = "\\"\\$\\in\\"",
replacement = "\\'$in\\'",
x = query_json)
... but this fails with an error.
I would be very grateful to know if:
The syntax problem that is preventing $in from working is actually the double quotes?
If double quotes is the problem, how do I replace them with single quotes without messing up the JSON format?
UPDATE:
The issue seems to occur when R is passing the query to the database, but I still can't work out exactly why.
If I try the query out in loopback explorer in the database, it works and using the export log ID produced, I can then fetch the results with httr::GET() in R. Example query results are shown below (sorry for the hashes - the main point is you can see the format of the returned values):
[1] "[{\"_id\":\"e59953b6-a106-4b69-9e25-1c54eef5264a\",\"updatedAt\":\"2022-09-12T20:08:39.554Z\",\"dateSampleTaken\":\"2022-08-16T00:00:00.000Z\",\"labName\":\"LNG_REFERENCE_DATA_CATEGORY_LAB_NAME_LAB_A\",\"sampleIdentifier\":\"LS0044-SCV2-PCR\",\"sequence\":{\"hasSequence\":false},\"person\":{\"visualId\":\"C-2022-0002\"}},{\"_id\":\"af5cd9cc-4813-4194-b60b-7d130bae47bc\",\"updatedAt\":\"2022-09-12T20:11:07.467Z\",\"dateSampleTaken\":\"2022-08-17T00:00:00.000Z\",\"labName\":\"LNG_REFERENCE_DATA_CATEGORY_LAB_NAME_LAB_A\",\"sampleIdentifier\":\"LS0061-SCV2-PCR\",\"sequence\":{\"hasSequence\":false},\"person\":{\"visualId\":\"C-2022-0003\"}},{\"_id\":\"b5930079-8d57-43a8-85c0-c95f7e0338d9\",\"updatedAt\":\"2022-09-12T20:13:54.378Z\",\"dateSampleTaken\":\"2022-08-16T00:00:00.000Z\",\"labName\":\"LNG_REFERENCE_DATA_CATEGORY_LAB_NAME_LAB_A\",\"sampleIdentifier\":\"LS0043-SCV2-PCR\",\"sequence\":{\"hasSequence\":false},\"person\":{\"visualId\":\"C-2022-0004\"}}]"
I'm trying to use a parameter inside of a JSON string, and would like to use an inner parameter to replace an GUID. I've changed the default parameter start and end characters since curly braces are used in JSON.
I've tried to do something like this, where the json param contains my json which is similar to this below.
{"DashboardGUID":"<Dash_GUID>"}
request_json = lr_eval_string("<json>");
lr_save_string(request_json, "request_json_param");
I'm expecting the lr_eval_string to replace the with the GUID that's in this parameter, what's the best why of replacing this ID in my JSON String?
Not sure what you are asking but I will put this here in case someone comes here in the future:
main.c
Action()
{
lr_eval_json("Buffer/File=my_json.json", "JsonObject=MJO",LAST);
lr_json_stringify("JsonObject=MJO","Format=compact", "OutputParam=newJsonBody",LAST);
lr_save_string(lr_eval_string(lr_eval_string("{newJsonBody}")),"tmp");
web_reg_find("Text={mydate}",LAST);
web_rest("POST",
"URL=http://myServer.microfocus.com/url",
"Method=POST",
"EncType=raw",
"Body={tmp}",
HEADERS,
"Name=Content-Type", "Value=application/json", ENDHEADER,
LAST);
return 0;
}
my_json.json
{
"LastActionId": 0,
"Updated": "{mydate}"
}
Okay so instead of doing what I'm thinking above I ended up creating an array of char's with this {"DashboardGUID":"<Dash_GUID>", someotherdata:"123"} in 10 different positions within the array. I then randomly selected an element from this array and when doing the lr_eval_string the parameter was replaced.
Hopefully this makes sense those looking to do something similar.
I am building a survey form through KoboToolbox. The web forms are Enketo based. I have some questions of the following type (before comma is first column and first row is data titles in XLSform format):
type, name
begin_group, group_farmexpenses_q5
note, group_farmexpenses_q5_note
integer, group_farmexpenses_q5_p1
text, group_farmexpenses_q5_column_1
end_group,
begin_group, group_farmexpenses_q5_1
note, group_farmexpenses_q5_1_note
integer, group_farmexpenses_q5_1_p1
text, group_farmexpenses_q5_1_column_1
end_group,
What i want to do is apply if statement for the integer values inside these two groups, however I get error. Here is what I do to apply if-statement :
if(${group_farmexpenses_q5_p1}=999, 0, ${group_farmexpenses_q5_p1})
if(${group_farmexpenses_q5_1_p1}=999, 0, ${group_farmexpenses_q5_1_p1})
since the above are calculate statements and each one is referred to as "expense1" and "expense2"
i then just add them
${expense1} + ${expense2}
I get error message:
if({group_farmexpenses_q5_1_p1} = 999, 0,
/model/instance[1]/data/group_wx0mk24/group_farmexpenses_q5_1/group_farmexpenses_q5_1_p1
), message: The expression is not a legal expression. (line:
undefined, character: undefined)
Any ideas how to fix this? I think there should be an easy fix but I don't know much about XLSform structures.
Proposed solution through online search for #Ziaw. Instead of first conditioning and then adding, both can be done in one step:
calculated data field compute this
if(${fexp_q1} = 999, 0, ${fexp_q1}) + if(${fexp_q2} = 999, 0,
${fexp_q2})
Here is my toy JSON:
"[[143828095,86.82525,78.50037,0.011764707,1.0,1,1],
[143828107,86.82525,78.50037,0.015686275,1.0,1,0],
[143828174,84.82802,83.49646,0.015686275,1.0,1,0],
[143828190,83.3301,92.4895,0.011764707,1.0,1,0],
[143828206,83.3301,92.4895,0.011764707,1.0,1,-1],
[143828251,119.482666,98.4848,0.03137255,1.0,2,1],
[143828325,123.30899,95.93237,0.027450982,1.0,2,0],
[143828334,128.47015,92.4895,0.027450982,1.0,2,0],
[143828351,128.47015,92.4895,0.027450982,1.0,2,-1],
[143828406,115.19141,60.514465,0.019607844,1.0,3,1],
[143828529,121.183105,61.51367,0.019607844,1.0,3,0],
[143828551,121.183105,61.51367,0.019607844,1.0,3,-1],
[143828696,105.502075,94.26935,0.023529414,1.0,8,1],
[143828773,105.502075,94.26935,0.023529414,1.0,8,-1],
[143829030,78.24274,58.18811,0.023529414,1.0,DEL,1],
[143829107,78.24274,58.18811,0.023529414,1.0,DEL,-1],
[143831178,127.47159,76.28339,0.023529414,1.0,8,1],
[143831244,127.47159,76.28339,0.023529414,1.0,8,-1]]"
Now I want to parse it (fromJSON()) but
DEL
within the JSON prevents me to do this.
Please advise how to fix it.
You can substitute "DEL" for, say, 0.
json_string <- "[[143828095,86.82525,78.50037,0.011764707,1.0,1,1], [143828107,86.82525,78.50037,0.015686275,1.0,1,0], [143828174,84.82802,83.49646,0.015686275,1.0,1,0], [143828190,83.3301,92.4895,0.011764707,1.0,1,0], [143828206,83.3301,92.4895,0.011764707,1.0,1,-1], [143828251,119.482666,98.4848,0.03137255,1.0,2,1], [143828325,123.30899,95.93237,0.027450982,1.0,2,0], [143828334,128.47015,92.4895,0.027450982,1.0,2,0], [143828351,128.47015,92.4895,0.027450982,1.0,2,-1], [143828406,115.19141,60.514465,0.019607844,1.0,3,1], [143828529,121.183105,61.51367,0.019607844,1.0,3,0], [143828551,121.183105,61.51367,0.019607844,1.0,3,-1], [143828696,105.502075,94.26935,0.023529414,1.0,8,1], [143828773,105.502075,94.26935,0.023529414,1.0,8,-1], [143829030,78.24274,58.18811,0.023529414,1.0,DEL,1], [143829107,78.24274,58.18811,0.023529414,1.0,DEL,-1], [143831178,127.47159,76.28339,0.023529414,1.0,8,1], [143831244,127.47159,76.28339,0.023529414,1.0,8,-1]]"
json_string <- gsub("DEL", 0, json_string) # You can make the zero any number you like
fromJSON(json_string)
using a json parser (http://json.parser.online.fr/), just deleting the "DEL" at the respective places seems to fix the issue.