How to use OR condition in mule dataweave for reading data from mongodb - mongodb

Mule 3.8.5 + Data-weave code query :-
I am trying to fetch records from mongodb which is equal to the code passed in input query param OR if the code is equal to static String "ALL".
the above is not working, can anyone suggest the correct syntax to write in transform message component?
%dw 1.0
%output application/json
---
{
"code" : [ upper inboundProperties."http.query.params".code or "ALL"]
}
Example if i pass code as "IND" it should return me records having code equal to "IND" or "ALL".
result = IND, ALL, ALL.

You can use default:
%dw 1.0
%output application/json
---
{
"code" : [ upper inboundProperties."http.query.params".code default "ALL"]
}
UPDATE.
Based on the mongo query syntax here: https://docs.mongodb.com/manual/tutorial/query-documents/
db.inventory.find( { status: { $in: [ "A", "D" ] } } )
Although you can express this query using the $or operator, use the $in operator rather than the $or operator when performing equality checks on the same field.
This should generate the json query in the correct format:
%dw 1.0
%output application/json
%var code = inboundProperties."http.query.params".code
---
{
"code" : { "\$in": [ upper code, "ALL" ] when code !=null otherwise ["ALL"] }
}
You might need to convert it to a string first before being used by the mongo query.

Related

How to fetch value from inner object in mongo query result

I'm new to mongodb.
I have this object in my collection:
{
"_id" : ObjectId("5b549be38d9f1c00160117d3"),
"name" : "Name of object",
"a" : {
"b" : {
"c" : 100
}
}
}
What interests me is the 100 value, I want to fetch it from the object.
When I query the collection like this:
db.getCollection('myCollection').find({}, {'name':1, 'a.b.c':1})
I only get the same object with the inner objects.
Is there a way to query it so that I will get a result like this:
{"Name": "Name of object", "c":100}
By using Mongo aggregate query you can get the result. In $project stage of Mongo aggregate query you can add the conditions as per requirement.
Please try this query, might you will get the result:
db.myCollection.aggregate({
$project: {
"name": "$name",
"c": "$a.b.c",
_id: 0
}
})
As suggested by #Mayuri, You can achieve this by using .aggregate() but if you wanted to look at difference between $project in aggregation (Vs) projection in .find(), check out :
So one first thing with $project is it is much more powerful & can accept a lot more features that are helpful to transform the fields. But projection in .find() is pretty straight forward that can accept only few things : projection i.e; value to a field in projection can be one of these :
1 or true to include the field in the return documents.
0 or false to exclude the field.
Projection Operators : $, $elemMatch, $slice, $meta
Actual Issue :
In your query when you're doing 'a.b.c':1 in projection it means you're returning c field in the output, As field c is nested in b & a the output structure doesn't change & you'll be getting the c value under the same structure, but if you use aggregation { $project: { "c": "$a.b.c" } } it means you're assigning value of "$a.b.c" to a field named c. How ? : So when $ is used against a field in aggregation it will access field's value, which helps for assignment.

MongoDB Query: $all with nested property

Hello I need some help with MongoDB:
My Document has the following property (generated by an Map with spring):
"filter":{"billingAccount_id":["multisim5"],"simulate":["true"]}
and i'm trying to find the document with the this code (generated by spring)
query.addCriteria(Criteria.where("filter").all(getMapWithValues()));
which results in
"filter" : { "$all" : [{ "billingAccount_id" : ["multisim5"] }] }
but i'm getting no result. What's to do here?
Thanks for help in advance
You're applying $all on an object (filter) instead of an array (filter.billingAccount_id). Change your request (and method getMapWithValues) to get something like :
{"filter.billingAccount_id" : { "$all" : ["multisim5"] }}
BUT $all is used to find array that contains, at least, all values provided in query. Since there's an unique element in $all param, $all is useless here, and the following query output the same result :
{"filter.billingAccount_id" : "multisim5"}
EDIT : if you want to query array with exact match ("multisim5" and nothin else), use the following :
{"filter.billingAccount_id" : { "$eq" : ["multisim5"] }}

How to write this MongoDb update operator

I have an 'applications' collection in the following form:
{
"_id" : "<id>",
"versions" : {
"2_2_1" : 5,
"2_2_2" : 38,
"2_2_3" : 76
}
}
I want to increment the version number based on the version of application that sends a request. How can I write the $inc operator for my update query?
I can't seem to get my query working because the incremented version number can always vary from request to request. I can't get the positional $ operator working correctly for my query.
You use "dot notation" in order to access the specifc value under "version", but also you are going to have to "build" the object key by whatever language you are using.
As a JavaScript example:
var request = "2_2_1";
var update = { "$inc": { } };
update["$inc"]["versions." + request] = 1;
This yields:
{ "$inc": { "versions.2_2_1": 1 } }
So you just perform the update:
db.collection.update({ "_id": id },update);
If that "request" version sub-key exists then it is "incremented" from it's previous value. If it is a "new" key then the initial value will be 1.

How do I get a value array instead a json array in mongo/node/mongoose?

I'm trying to simulate a join in a mongo query so I'm taking the results of my 1st query and then passing it as a $in filter to my 2nd query.
Unfortunately the results of my 1st query returns an array of json objects like so
[ { _id: 4ecd830da046050100000025 },
{ _id: 4ecd84a0a046050100000085 } ]
and the $in filter doesn't return anything because they are json objects instead of a value array. I can manually transform that array but is there a built in method or function that I can use? Also, is there a way I can have mongo return the value array instead? Currently I am calling the find query as such
Likes.find {liker:"Me"}, {_id:1}, {safe:true}
And here is my 2nd query
Post.find {_id:{$in:likes}}
I was hoping for something like
Post.find {_id:{$in:likes._id}}
Although there is no general solution to your question in the case of $in clauses you can use the result of a distinct operation :
> db.test.save({a:1})
> db.test.save({a:2})
> db.test.save({a:3})
> db.test.save({a:4})
> ids = db.test.distinct("_id", {a:{$gt:2}})
[
ObjectId("4ece45c2c951f11718678574"),
ObjectId("4ece45c4c951f11718678575")
]
> db.test.find({_id:{$in:ids}})
{ "_id" : ObjectId("4ece45c2c951f11718678574"), "a" : 3 }
{ "_id" : ObjectId("4ece45c4c951f11718678575"), "a" : 4 }
Hope that helps!

Is it possible to cast in a MongoDB-Query?

When I have two MongoDB documents like this...
db.test.insert( {"value" : "10123"} );
db.test.insert( {"value" : "160"} );
The result of a query like:
db.test.find({"value" :{$gt : "12"} });
is..
{ "_id" : ObjectId("4c6d1b92304326161b678b89"), "value" : "160" }
It's obvious, that a string comparison is made, so that my first value is not returned.
Is there any way to cast within the query?
Something like:
db.test.find({ (int) "value" :{$gt : 12} });
would be great. A query like
db.test.find({"value" :{$gt : 12} }); // without the quotes around "12"
returns nothing.
You can use the following JavaScript expression:
db.test.find("this.value > 12")
This uses JavaScript's automatic conversion from string to number.
I have a similar workaround, i find that if you can use the mongo shell, you can write an statement to do this in javascript, but capable of using indexes.
var myItems = []
var it = db.test.find({},{value:1})
while (it.hasNext()){
var item = it.next();
if(parseInt(item.value) > 12)
myItems.push(item);
}
If you want this to run faster than previus solution, you have to ensure the index on the value field.
Type casting in MongoDB is available after version >= 4.0. Check MongoDB's aggregation operator $convert and similar operators. Since you wanted to convert string to int you can use $toInt:
db.collection.find({ $expr: { $gt: [ { $toInt: "$value" }, 12 ] } })
Test : mongoplayground
Note :
Here we're converting value which is a string field to int on the fly & Since it got converted to int - we're comparing it to input of type int. Your output documents will still have original type for value field which is string (we're not actually changing type in response docs, if needed use aggregation & it's stage $project to see int values for field value in response docs).
Since we're using aggregation operators in .find() we need to wrap everything in $expr.
Even though this is pretty common nowadays & is easy to do, but remember we're casting string to int on every Read, rather if you can take care of this on Writes or Updates it would be easy & more efficient.
To convert String into int use this
db.test.find({'year': {$type: 2}}).forEach(
function (x) {
x.value=new NumberInt(x.value);
db.test.save(x)}
)
And after that you can directly query like :
db.test.find({"value" :{$gt : 12} });
$gt wasn't set for this use case. You would have to use regex for strings. Probably easier to just create a new field with the number as a number.