check if a field value exit in array - MongoDB - mongodb

I'm using MongoDB and i have the following schema of person collection:
Person {
age: [number]
}
i want to check if the age of a person exist in array, for exemple [15, 20, 12, 0]. i need something like $in operator but in reverse.
schema:
initiatives : {
ressources: [
{ departement: ObjectId }
{ departement: ObjectId }
]
)

You can use $expr with $in:
Person.find({ $expr: { $in: [ "$age", [15, 20, 12, 0] ] } })
EDIT: to compare arrays you need $setIntersection and $size operators, try:
Person.find({
$expr: {
$gt: [
{
$size: {
$setIntersection: [
[
"15",
"a",
"12",
"0"
],
"$age.x"
]
}
},
0
]
}
})

Related

How to match an element in array? MongoDB aggregation

I need to check all the documents whose specific field is contained in an array.
For example I have the array
arr = ['a', 'b', 'a']
I want to match all the documents that has field my_letter equal to a or b.
I have the documents:
[
{
_id: ObjectID(),
my_letter:'d'
},
{
_id: ObjectID(),
my_letter:'a'
},
{
_id: ObjectID(),
my_letter:'b'
}
]
I want the aggregation to return
[
{
_id: ObjectID(),
my_letter:'a'
},
{
_id: ObjectID(),
my_letter:'b'
}
]
I tried this in my $match pipeline
{
$match: {
_id: {
$elemMatch: {
$or: [
{ $eq: ["a"] },
{ $eq: ["b"] },
],
},
},
},
},
Of course it doesn't work. How would You suggest to complete the $match pipeline?
db.collection.find({
my_letter: {
$in: [ "a", "b" ]
}
})
mongoplayground
db.collection.aggregate([
{
$match: {
my_letter: {
$in: [ "a", "b" ]
}
}
}
])
mongoplayground

MongoDB Aggregation: How to check if an object containing multiple properties exists in an array

I have an array of objects and I want to check if there is an object that matches multiple properties. I have tried using $in and $and but it does not work the way I want it to.
Here is my current implementation.
I have an array like
"choices": [
{
"name": "choiceA",
"id": 0,
"l": "k"
},
{
"name": "choiceB",
"id": 1,
"l": "j"
},
{
"name": "choiceC",
"id": 2,
"l": "l"
}
]
I am trying to write aggregation code that can check if there is an object that contains both "id":2 and "l":"j" properties. My current implementation checks if there is an object containing the first property then checks if there is an object containing the second one.
How can I get my desired results?
Below, see my aggregation query. The full code is here
db.poll.aggregate([
{
"$match": {
"_id": 100
}
},
{
$project: {
numberOfVotes: {
$and: [
{
$in: [
2,
"$choices.id"
]
},
{
$in: [
"j",
"$choices.l"
]
}
]
},
}
}
])
The above query returns true yet there is no object in the array both of the properties id:2 and "l":"J". I know the code works as expected. How can I get my desired results?
You want to use something like $elemMatch
db.collection.find({
choices: {
$elemMatch: {
id: 2,
l: "j"
}
}
})
MongoPlayground
EDIT
In an aggregation $project stage I would use $filter
db.poll.aggregate([
{
"$match": {
"_id": 100
}
},
{
$project: {
numberOfVotes: {
$gt: [
{
$size: {
$filter: {
input: "$choices",
as: "choice",
cond: {
$and: [
{
$eq: [
"$$choice.id",
2
]
},
{
$eq: [
"$$choice.l",
"j"
]
}
]
}
}
}
},
0
]
}
}
}
])
MongoPlayground

how to test each element of array in mongodb subdocument

I have mongodb document with the following data:
amenities[
{
amenity_id:52,
Amenity:"AC"
},
{
amenity_id:23,
Amenity:"Free Parking"
}
]
I want to match each amenity_id element of the array with particular value and return true or false using condition $cond. I used
"$project":{'Free Parking':{'$cond':{'if':{'$in':['amenities.amenityId',[23]]},'then':'True','else':'False'}}
If a document contains amenity_id= 52 then a query has to return False.
It is returning false irrespective of the menityId. The amenity Id could be list hence using $in. How can i test each element ?
Considering your input collection is
[
{
amenities: [
{
_id: 52,
Amenity: "AC"
},
{
_id: 23,
Amenity: "Free Parking"
}
]
}
]
using aggregate pipeline $map
db.collection.aggregate([
{
$project: {
amenites: {
$map: {
input: "$amenities",
as: "item",
in: {
Amenity: "$$item.Amenity",
_id: "$$item._id",
isValid: {
$cond: {
if: {
$eq: [
"$$item._id",
23
]
},
then: true,
else: false
},
}
}
}
}
}
}
])
You'll get result as:
[
{
"amenites": [
{
"Amenity": "AC",
"_id": 52,
"isValid": false
},
{
"Amenity": "Free Parking",
"_id": 23,
"isValid": true
}
]
}
]
use $unwind operation in mongodb it will unwind the array field in to multiple documents
Please refer this url - https://docs.mongodb.com/manual/reference/operator/aggregation/unwind/
ex:
{
_id :1,
field: [1,2,3]
}
this will be converted to the following using $unwind,
[
{_id, field:1},
{_id, field:2},
{_id, field:3}
]
after $unwind you can run a match query, with $in query,
Ex:
{
$match: {
field: {$in: [1,2]}
}
}

Multiple conditions for field in mongoDB with $or

I'd like to retrieve all documents from a MongoDB collection, where users field is either numeric or a string, consisting of all digits (1, 2, 19, or "4", "19", ...)
I query:
db.getCollection('collection').find(
{
users: { $or : [ { $type: [1, 16, 18, 19] },
{ $regex: /^[0-9]+$/ } ]
}
}
)
... and get the error "Unknown operator $or".
This works:
db.getCollection('collection').find(
{
$or: [
{users: { $type: [1, 16, 18, 19] } },
{users: { $regex: /^[0-9]+$/ }}
]
}
)
Why doesn't the first variant work?
$or must itself contains the field upon which you want to query. Your second query contains the field.
$or :[{field_name:Match_expression},{field_name:Match_expression}...{field_name:Match_expression}]
db.getCollection('collection').find( {
$and : [
{ $or : [ { $type: [1, 16, 18, 19] } ] },
{ $or : [ {users: { $regex: /^[0-9]+$/ } ] }
]
} )
this should work
EDIT
This is where it was answered before

MongoDB - Find only documents where their arrays contains the query's array

How to get all documents with a find query where the queried array fields are exists in the document?
{
name: 'test1',
"array": [
{
"name": "100",
"subArray": [
"arr1"
]
},
{
"name": "200",
"subArray": [
"arr2",
"arr3"
]
}
]
}
If i use this query in the find({}) it gives back not only the good results:
$and: [
{'array.name': '100'}, {'array.subArray': 'arr1'},
{'array.name': '200'}, {'array.subArray': 'arr2'}
]
You need to use the $elemMatch operator. Your query should look like this:
$and: [
{ array: { $elemMatch: { name: '100', subArray: 'arr1' } } },
{ array: { $elemMatch: { name: '200', subArray: 'arr1' } } }
]