MongoError: Expression $in takes exactly 2 arguments. 1 were passed in - mongodb-query

below is my query:
while executing below query getting mongoerror : Expression $in takes exactly 2 arguments. 1 were passed in.
i am using $in Comparison operator
{
"$expr": {
"$not": {
"$eq":{
"$and": [
{
"PrName": {
"$in": [
"pname"
]
}
},
{
"AccountId": {
"$in": [
"34562",
"88765",
"87654",
"12345"
]
}
}
]
}
}
}
}

When you use $expr, the operator expressions syntax changes a little:
{ $in: [ <expression>, <array expression> ] }
{
"$expr": {
"$not": {
"$and": [
{
"$in": [
"$PrName",
[
"pname"
]
]
},
{
"$in": [
"$AccountId",
[
"34562",
"88765",
"87654",
"12345"
]
]
}
]
}
}
}

Related

Query item in nested array

Customer appointments with top level locationId sample data set:
[
{
"locationId": 9999,
"customerAppointments": [
{
"customerId": "1",
"appointments": [
{
"appointmentId": "cbbce566-da59-42c2-8845-53976ba63d56",
"locationName": "Sullivan St"
},
{
"appointmentId": "5f09e2af-ddae-47aa-9f7c-fd1001a9c5e6",
"locationName": "Oak St"
}
]
},
{
"customerId": "2",
"appointments": [
{
"appointmentId": "964a3c1c-ccec-4082-99e2-65795352ba79",
"locationName": "Kellet St"
}
]
},
{
"customerId": "3",
"appointments": []
}
]
},
{
...
},
{
...
}
]
I need to pull out appointment by locationId and customerId and only get the appointment for that customerId e.g
Sample response:
[
{
"appointmentId": "964a3c1c-ccec-4082-99e2-65795352ba79",
"locationName": "Kellet St"
}
]
Tried below query, but it just returns all records for all customers ids (which is kind of expected):
db.getCollection("appointments").find(
{
"locationId" : NumberInt(9999),
"customerAppointments" : {
"$elemMatch" : {
"customerId" : "2"
}
}
}
);
But how can I get just the appointment record for a specific customerId?
When asking this question I was unaware of the older version of MongoDB driver (< v5) so we cannot use the $getField operator.
However, this query seems to work well:
db.getCollection("appointments").aggregate([
{
$match: {
"locationId": NumberInt(9999)
}
},
{
$unwind: "$customerAppointments"
},
{
$match: {
"customerAppointments.customerId": "2"
}
},
{
$project: {
appointments: "$customerAppointments.appointments"
}
}
]);
Yields:
{
"_id" : ObjectId("63eebe95c7a0da54804c1db2"),
"appointments" : [
{
"appointmentId" : "964a3c1c-ccec-4082-99e2-65795352ba79",
"locationName" : "Kellet St"
}
]
}

Unable to filter Array of objects having dynamic keys using dataweave

I want to filter this array of object based on EmployeeStatus which should be only Resigned and Terminated but not active. Here the keys are different for each object and hence I am unable to apply logic like item.key.EmployeeStaus=="Resigned" or "Terminated" .Any suggestions or hint would be helpful for me.
Input Payload
[
{
"626433000000196190": [
{
"EmailID": "rubyrichards#zylker.com",
"Employeestatus": "Resigned"
}
]
},
{
"626433000000196184": [
{
"EmailID": "morganfinely#zylker.com",
"Employeestatus": "Active"
}
]
},
{
"626433000000196178": [
{
"EmailID": "jenniferjackson#zylker.com",
"Employeestatus": "Active"
}
]
},
{
"626433000000196166": [
{
"EmailID": "daveduken#zylker.com",
"Employeestatus": "Terminated"
}
]
}
]
Required Output
[
{
"EmailID": "rubyrichards#zylker.com",
"Employeestatus": "Resigned"
},
{
"EmailID": "daveduken#zylker.com",
"Employeestatus": "Terminated
}
]
Maybe something like this:
Input
[
{
"626433000000196190": [
{
"EmailID": "rubyrichards#zylker.com",
"Employeestatus": "Resigned"
}
]
},
{
"626433000000196184": [
{
"EmailID": "morganfinely#zylker.com",
"Employeestatus": "Active"
}
]
},
{
"626433000000196178": [
{
"EmailID": "jenniferjackson#zylker.com",
"Employeestatus": "Active"
}
]
},
{
"626433000000196166": [
{
"EmailID": "daveduken#zylker.com",
"Employeestatus": "Terminated"
}
]
}
]
Script
%dw 2.0
output application/json
---
flatten(payload map
($ mapObject {
b: $ filter ($.Employeestatus != "Active")
}).b -[])
Output
[
{
"EmailID": "rubyrichards#zylker.com",
"Employeestatus": "Resigned"
},
{
"EmailID": "daveduken#zylker.com",
"Employeestatus": "Terminated"
}
]
Here's another take:
%dw 2.0
output application/json
var data = [
{
"626433000000196190": [
{
"EmailID": "rubyrichards#zylker.com",
"Employeestatus": "Resigned"
}
]
},
{
"626433000000196184": [
{
"EmailID": "morganfinely#zylker.com",
"Employeestatus": "Active"
}
]
},
{
"626433000000196178": [
{
"EmailID": "jenniferjackson#zylker.com",
"Employeestatus": "Active"
}
]
},
{
"626433000000196166": [
{
"EmailID": "daveduken#zylker.com",
"Employeestatus": "Terminated"
}
]
}
]
---
flatten({(data)} pluck $) filter not ($.Employeestatus == "Active")
I 'll add explanations later on.
EDIT: Here's the explanation and links to the DW documentation:
I make use of the dynamic elements feature {(data)} to destroy the array and collapse all enclosed objects into an object.
I then use pluck to get just the values in an array.
I make use of flatten to collapse the first level of sub-arrays, because the values we just plucked are also arrays. You now have a flat array.
Now I make use of filter to remove eliminate all records that fail the assertion to the right.
You can filter the records by transversing the structure. First an array, using map. Each element is an object with a single key, so let's use mapObject, then filter. I didn't try to remove the empty arrays.
%dw 2.0
output application/json skipNullOn="everywhere"
fun filterEmployeeStatus(e) = e filter ($.Employeestatus == "Resigned" or $.Employeestatus == "Terminated")
---
payload map
( $ mapObject ((value, key, index) -> (key): filterEmployeeStatus(value) ) )
Output:
[
{
"626433000000196190": [
{
"EmailID": "rubyrichards#zylker.com",
"Employeestatus": "Resigned"
}
]
},
{
"626433000000196184": [
]
},
{
"626433000000196178": [
]
},
{
"626433000000196166": [
{
"EmailID": "daveduken#zylker.com",
"Employeestatus": "Terminated"
}
]
}
]

getting lvalue and rvalue of a declaration

Im parsing C++ with ANTLR4 grammar, I have a visitor function for visitDeclarationStatement. In the C++ code that Im trying to parse Person p; or a declaration of any custom type, in the tree I get two similar nodes and I cannot differentiate between the Lvalue and Rvalue!
"declarationStatement": [
{
"blockDeclaration": [
{
"simpleDeclaration": [
{
"declSpecifierSeq": [
{
"declSpecifier": [
{
"typeSpecifier": [
{
"trailingTypeSpecifier": [
{
"simpleTypeSpecifier": [
{
"theTypeName": [
{
"className": [
{
"type": 128,
"text": "Person"
}
]
}
]
}
]
}
]
}
]
}
]
},
{
"declSpecifier": [
{
"typeSpecifier": [
{
"trailingTypeSpecifier": [
{
"simpleTypeSpecifier": [
{
"theTypeName": [
{
"className": [
{
"type": 128,
"text": "p"
}
]
}
]
}
]
}
]
}
]
}
]
}
]
},
{
"type": 124,
"text": ";"
}
]
}
I want to be able to get Variable Type and Variable Name separately. What is the right way of doing that? How can I change the g4 file to get those results in a way that I can differentiate between the type and the name?
Thanks
You don't need to change the grammar. In case of Person p;, which is matched by:
declSpecifierSeq: declSpecifier+ attributeSpecifierSeq?;
the first child of declSpecifierSeq (which is declSpecifier+) will be a List of declSpecifier-contexts, of which the first is the type and the second the name.

How can I define jsonPath for given json?

{
"name": "ninja",
"contry": "India",
"Account": [
{
"id": "123",
"orgId": 223,
"investment": [
{
"invetmentId": "111",
"name": "India tech",
"performance": [
{
"id": "123",
"performanceSet": [
{
"amount": "231",
"currency": "USD"
},
{
"amount": "250",
"currency": "IND"
}
]
}
]
}
]
}
]
}
So I have to select the amount where the currency is USD?
And I tried it as "$.Account..investment.performance..performanceSet.amount[?(#.currency=~/.*USD/)]"
This JsonPath should work:
$..performanceSet[?(#.currency == "USD")].amount
Tested on:
{
"name":"ninja",
"contry":"India",
"Account":[
{
"id":"123",
"orgId":223,
"investment":[
{
"invetmentId":"111",
"name":"India tech",
"performance":[
{
"id":"123",
"performanceSet":[
{
"amount":"231",
"currency":"USD"
},
{
"amount":"250",
"currency":"IND"
}
]
}
]
},
{
"invetmentId":"112",
"name":"India tech 2",
"performance":[
{
"id":"124",
"performanceSet":[
{
"amount":"235",
"currency":"USD"
},
{
"amount":"250",
"currency":"IND"
}
]
}
]
}
]
}
]
}
which returns:
[
"231",
"235"
]
A good way to try it out is this site: https://jsonpath.com/
Read the docs: https://github.com/intuit/karate#jsonpath-filters
* def temp = $..performanceSet[?(#.currency=='USD')]
* match temp[0].amount == '231'
You can try it this way
$.Account..investment.performance..performanceSet.amount[?(#.currency=~/.*USD/)]

MongoDB - How to make a query to get the average usage?

Here is how the documents in db look like.
/* 1 */
{
"_id" : 1,
"feat" : {
"processName": [
{
"value" : {
"value": "Process1"
}
}
],
"processUsage": [
{
"value" : {
"value": 23.21
}
}
]
}
}
/* 2 */
{
"_id" : 2,
"feat" : {
"processName": [
{
"value" : {
"value": "Process2"
}
}
],
"memoryUsage": [
{
"value" : {
"value": 2.411502e+05
}
}
]
}
}
/* 3 */
{
"_id" : 3,
"feat" : {
"processName": [
{
"value" : {
"value": "Process1"
}
}
],
"processUsage": [
{
"value" : {
"value": 67.42
}
}
]
}
}
/* 4 */
{
"_id" : 4,
"feat" : {
"processName": [
{
"value" : {
"value": "Process3"
}
}
],
"processUsage": [
{
"value" : {
"value": 39.97
}
}
]
}
}
/* 5 */
{
"_id" : 5,
"feat" : {
"processName": [
{
"value" : {
"value": "Process2"
}
}
],
"processUsage": [
{
"value" : {
"value": 21.05
}
}
]
}
}
Each process has entries with processUsage and memoryUsage. What I am interest in is the average processUsage. So, I'd like to ignore the entries with memoryUsage.
I tried $match + $group in an aggregate with $avg, but for each process I just got back as average 0.00000000.
Then I tried my luck with mapReduce using javascript, unfortunately it did not work out either.
Could someone just show me how to do that? By the way, I am using Robomongo 0.8.5
Edit:
The query looks like this:
db.database.aggregate([
{ $match : {"$feat.processUsage.value.value": {$gt : -1}
},
{
$group: {_id: "$feats.processName.value.value", average: {$avg:
"$feats.processUsage.value.value"}
}
])
You can use the following aggregate query:
db.test.aggregate(
[
{
$unwind : "$feat.processUsage"
},
{
$group: {
_id: "$feat.processName.value.value",
average: {$avg:"$feat.processUsage.value.value"}
}
}
]
)
Unwinding in the initial phase will let you filter documents that has processUsage key in document.
Result:
{ "_id" : [ "Process2" ], "average" : 21.05 }
{ "_id" : [ "Process3" ], "average" : 39.97 }
{ "_id" : [ "Process1" ], "average" : 45.315 }