Conditional filtering in mongoDB - mongodb

Can I use one of the $and filters conditionally, ie. when some condition is met I would like to use the filter otherwise do not use filter:
Collection.find({
$and: [
{ date },
{ room: [isConditionMet] ? room : [do not use room filter at all] },
]
}
Is it possible on mongo query level?

Isn't it the same as using $or?
Collection.find({
$and: [
{ date: ... },
{ $or: [
{isConditionNOTmet},
{room: ... }
]}
]
})

Related

SQL equivalent queries in MongoDB

I'm converting my SQL queries into MongoDB. I have the following SQL statement which checks an input and perform the query accordingly.
(score_min = -1 OR Scores BETWEEN score_min AND score_max)
Scores is a field name, which I want to filter
Still couldn't figure out the best way to perform this query in a MongoDB aggregate pipeline. Any suggestions please?
You can achieve the behaviour with a $expr in a simple find. Not a must to use aggregation pipeline.
db.collection.find({
$expr: {
$or: [
{
// $eq: [<score_min>, -1]
$eq: [
<score_min>,
-1
]
},
{
$and: [
{
// $gte: ["$Scores", <score_min>]
$gte: [
"$Scores",
<score_min>
]
},
{
$lte: [
// $gte: ["$Scores", <score_max>]
"$Scores",
<score_max>
]
}
]
}
]
}
})
Here is the Mongo playground for your reference.

$and operation syntax

I should take a data with condition:
(Founded in 2004 OR Founded in October) AND (social OR web)
I used to try like this:
db.companies.find({
$or: [
{"founded_year": 2004},
{"founded_month": 10}
],
$or: [
{"category_code": "web"},
{"category_code": "social"}
]
}).count()
but this goes wrong. The corrent answer is:
db.companies.find({ "$and": [
{ "$or": [ { "founded_year": 2004 },
{ "founded_month": 10 } ] },
{ "$or": [ { "category_code": "web" },
{ "category_code": "social" }]}]}).count()
Why should i use $and operator in the inner {}? I thought i didn't have to write this operator and i can just list the conditions in {} with comma, because in MongoDB university course there where this expression:
In the query
{
"$or": [
{"founded_year": 2004},
{"founded_month": 10}
],
"$or": [
{"category_code": "web"},
{"category_code": "social"}
]
}
you have two keys named $or. Or a mongo query follows the JSON notation. And in JSON format, only the last key with the duplicate name is going to be used.
Using the $and will fix this issue. Because $and is a list, you will not have anymore an object containing the two same keys

Using $if or $ifNull condition inside a $match that will be executed in Jaspersoft Studio

{
$match: {
$expr: {
$or: [
{$ifNull : [$P{departmentuid},"warduid":{"$eq": {"$oid":$P{warduids} } } ] },
{$ifNull : [$P{warduids},"orderdepartmentuid": {"$eq": {"$oid":$P{departmentuid} } } ] }
]
}
}
},
I am trying to create a query that will be executed from Jaspersoft Studio. Now, the parameter that will be sent to the query is either of the two set parameters, so I created a $match that has a condition that it will only filter one parameter that will be received.
I am not quite sure if im doing the right query for this. Hope someone can help. Thanks!
The parameters that will be recieved from jaspersoft studio is either $P{departmentuid} or ${warduids}
The logic will just be, If the query recieved $P{departmentuid} parameter, It will apply departmentuid only in the whole query but if it received $P{warduid} it will apply warduid only.
Assuming when $P{departmentuid} or ${warduids}, they will be supplemented the value of null.
You could then do the followings:
db.collection.aggregate([
{
$match: {
$expr: {
$or: [
{
$and: [
{$eq: [null, $P{warduids}]},
{$eq: ["$orderdepartmentuid", $P{departmentuid}]}
]
},
{
$and: [
{$eq: [null, $P{departmentuid}]},
{$eq: ["$warduid", $P{warduids}]}
]
}
]
}
}
}
])
Here is the Mongo playground when $P{warduids} is null.
And here is the Mongo playground when $P{departmentuid} is null

how to use $elemMatch on array specifying an upper field as part of the query

I'd like to retrieve for a specific user, his chats with unread messages.
Lets say I have a simplified chat model like that :
{
lastMessageAt: Date,
participants: [
{
user: String(id),
lastReadAt: Date
}
]
}
How can I achieve my query ?
I have tried several thing like with $elemMatch, but lastMessageAt is unknown at this level...
ChatDB.find({
'participants': {
$elemMatch: { user: '12345', lastReadAt: { $lt: '$lastMessageAt' } }
}
}
Thanks in advance for your help ! :)
$elemMatch operator will find those documents in ChatDB collection that have at least 1 element in participants that matches your criteria. Also my research ended with the conslusion that it is not yet possible to access other document field in $elemMatch operator. Anyway, if this is your goal, then you can use this query:
ChatDB.aggregate([
{
$match: {
"participants.user": "12345",
$expr: {
$lt: [
"$participants.lastReadAt",
"$lastMessageAt"
]
}
}
}
])
Mongo playground
If you also want to filter participants that really matched the criteria, then you need to add a projection stage:
ChatDB.aggregate([
{
$match: {
"participants.user": "12345",
$expr: {
$lt: [
"$participants.lastReadAt",
"$lastMessageAt"
]
}
}
},
{
$project: {
participants: {
$filter: {
input: "$participants",
as: "participant",
cond: {
$and: [
{
$eq: [
"$$participant.user",
"12345"
]
},
{
$lt: [
"$$participant.lastReadAt",
"$lastMessageAt"
]
}
]
}
}
}
}
}
])
Mongo playground
I have found the solution witch is to use the aggregator with the $unwind operator.
await ChatDB.aggregate([
{
$unwind: '$participants'
},
{
$match: {
'participants.user': '12345',
$expr: {
$lt: [
'$participants.lastReadAt',
'$lastMessageAt'
]
}
}
}]);
Hope this will be usefull

Mongo db $and condition over two fields

I have a collection in MongoDb Tweet Training, in these collection i collect specific information about a tweet. I have three fields (sentiment, Categorie and tekst). I wan't to execute a query which identify all items where the "Categorie" is equal to "Rabobank" and the sentiment is equal to "neutraal" or the "Categorie" is equal to "Ing" and the sentiment is equal to "neutraal".
there fore i use the following query:
db.TweetTraining.find( {
$and: [
{ $or: [ { sentiment:"neutraal" } ,{ Categorie:"Rabobank" } ]},
{ $or: [ { sentiment:"neutraal" } ,{ Categorie:"Ing" } ]}
]})
but in stead of getting the right results I get also other Cattegorie's.
Change your query to the following
db.TweetTraining.find({$or: [
{$and: [{ sentiment: "neutraal" } ,{ Categorie: "Rabobank" }]} ,
{$and: [{ sentiment:"neutraal" } ,{ Categorie:"Ing"}]}]
})