MongoDb Query Filtering with arithmetic expression - mongodb

i have a query in sql that I wan't to translate into the MongoDb query.
The statement is:
select * from TBA where a/b < c/d
a,b,c are columns in the table tba and d is a constant
How can I rewrite this statement into the MongoDb query language?
I have a document collection called "TBA" where all documents are stored. Now I want to find out which documents fulfill the condition "a/b < c/d".
Thank you in advance.
Best regards,
user12682244

If you want to do a calculation using the values stored in the document, you need to use a pipeline:
db.collection.aggregate([
{$match: {
$expr: {
$lt: [
{$divide: ["$a", "$b"]},
{$divide: ["$c", d]}
]
}
}
}
])
See how it works on the playground example

Related

How to $inc a field by another field in the same document?

How do I use the value of another field in $inc to define how much to increase?
Example-
Some doc
{_id: obi, length: 256, delta: 6}
Here, I want to increase the length by delta increment.
Pseudocode would be
db.collection.update({}, $inc: {length: $delta});
Thanks for helping...
Simple update operation can't allow to use internal fields in another fields, either its any of the operators,
For the solution you can use update with aggregation pipeline starting from MongoDB 4.2,
use $add/$sum any operator from both to sum the both fields number
db.collection.update({},
[{
$set: {
length: {
$add: ["$length", "$delta"]
}
}
}]
)
Playground

How to write group by query for embedded array of document in mongodb

I have a collection in below format
{customerID:1,acctDetails:[{accType:"Saving",balance:100},{accType:"checking",balance:500}]}
{customerID:2,acctDetails:[{accType:"Saving",balance:500}]}
I want to find total balance by acctType. I tried below query.
db.<collectionName>.aggregate([{$group:{_id:"$acctDetails.accType",totalBalance:{$sum:"$accDetails.balace"}}}])
But it is not giving right result.
I think that this might solve your problem. You first need to use $unwind to transform each array element in a document, then use $group to sum the total balance by account type.
db.collection.aggregate([
{"$unwind": "$acctDetails"},
{
"$group": {
"_id": "$acctDetails.accType",
"totalBalance": {"$sum": "$acctDetails.balance"}
}
}
])
Working Mongo playground

How to compare one field with combined fields in mongodb

I have a collection like this
sample document
{
"field1":"one",
"field2":"two",
"field3":"three",
...some more key values
}
Now i have field value which is combination of field1, field2 and field3 values. i.e. for above document i have field = "onetwothree"
One option is to seggregate that field to 3 different fields but it is not possible because its pattern is not fixed
so I want to compare like this
db.collection.find({"filed1+field2+field3":field})
but it is not possible so one solution is to find all documents from collection and compare one by one but it is not optimized way to do this. So is it any better solution to do this?
Starting with MongoDB v3.6 you can run this query:
db.collection.find({
$expr: {
$eq: [
"onetwothree",
{ $concat: [ "$field1", "$field2", "$field3" ] }
]
}
})
Here's the documentation on $concat and $expr.

SELECT avg(rate) FROM ratings WHERE sid=1 in MongoDB

How to implement equivalent of this SQL command in MongoDB?
SELECT avg(rate) FROM ratings WHERE sid=1
No need to grouping.
Yes there is aggregation framework in mongodb where you can make a pipeline of stages you want for query.
db.collection.aggregate([
{
$match: {
"sid": 1
}
},
{
$project: avg(rate): {
$avg: "$rate"
}
}
])
As you know in sql query where part is applied first that's why we've place $match pipeline at first. $match in mongodb is somehow equivalent to where i SQL and there is $avg in mongodb which works the same as AVG in SQL
To solve this, use $avg within the $group aggregation pipeline element. Basic pipeline flow:
match on sid=1 (your WHERE clause)
group by sid (there's only one sid to group by at this point, because the others are filtered out via match), and generate an average within the group'd content
Your pipeline would look something like:
db.rates.aggregate(
[
{ $match: {"sid":1}},
{ $group: { _id: "$sid", rateAvg: {$avg: "$rate" } }}
])

How to return documents where two fields have same value [duplicate]

This question already has answers here:
MongoDb query condition on comparing 2 fields
(4 answers)
Closed 3 years ago.
Is it possible to find only those documents in a collections with same value in two given fields?
{
_id: 'fewSFDewvfG20df',
start: 10,
end: 10
}
As here start and end have the same value, this document would be selected.
I think about something like...
Collection.find({ start: { $eq: end } })
... which wouldn't work, as end has to be a value.
You can use $expr in mongodb 3.6 to match the two fields from the same document.
db.collection.find({ "$expr": { "$eq": ["$start", "$end"] } })
or with aggregation
db.collection.aggregate([
{ "$match": { "$expr": { "$eq": ["$start", "$end"] }}}
])
You have two options here. The first one is to use the $where operator.
Collection.find( { $where: "this.start === this.end" } )
The second option is to use the aggregation framework and the $redact operator.
Collection.aggregate([
{ "$redact": {
"$cond": [
{ "$eq": [ "$start", "$end" ] },
"$$KEEP",
"$$PRUNE"
]
}}
])
Which one is better?
The $where operator does a JavaScript evaluation and can't take advantage of indexes so query using $where can cause a drop of performance in your application. See considerations. If you use $where each of your document will be converted from BSON to JavaScript object before the $where operation which, will cause a drop of performance. Of course your query can be improved if you have an index filter. Also There is security risk if you're building your query dynamically base on user input.
The $redact like the $where doesn't use indexes and even perform a collection scan, but your query performance improves when you $redact because it is a standard MongoDB operators. That being said the aggregation option is far better because you can always filter your document using the $match operator.
$where here is fine but could be avoided. Also I believe that you only need $where when you have a schema design problem. For example adding another boolean field to the document with index can be a good option here.
this query is fast, since least function calls are involved,
Collection.find("this.start == this.end");