mongodb search case insensitive not working - node.js

below is DB
[
{
"name": "new İSLAND"
},
{
"name": "old İSLAND"
}
]
below is query :
db.collection.find({
"name": {
"$regex": "İS",
"$options": "i"
}
})
this brings the result :
[
{
"_id": ObjectId("5a934e000102030405000000"),
"name": "new İSLAND"
},
{
"_id": ObjectId("5a934e000102030405000001"),
"name": "old İSLAND"
}
]
what I want is, below query should bring the results aswell but not bringing:
db.collection.find({
"name": {
"$regex": "is",
"$options": "i"
}
})
result: no document found
https://mongoplayground.net/p/_o0CjQqL21H
How can fix it, result should accept case insensitive

Related

MongoDB Aggregation - How to condition for $set

I am unwinding a lookup joined by { preserveNullAndEmptyArrays: true } option to include documents whose sizes field is null, missing, or an empty array. But in my case, I need to join nested lookup and the output result is not as I expected.
Specifically, I am being to set a new buyer field by the $set operator from lookup but if this lookup is null or empty array it will return [ { } ] and I don't want that. How can I replace [ { } ] with empty array?
The result I got:
[
{
"_id": ObjectId("5a934e000102030405000000"),
"buyers": [
{
"_id": ObjectId("5a934e000102030405000003"),
"buyer": {
"_id": ObjectId("5a934e000102030405000004"),
"display_name": "Phineas",
"user_id": "123"
},
"post_id": 1,
"user_id": "123"
}
],
"content": "content book 1",
"title": "title book 1"
},
{
"_id": ObjectId("5a934e000102030405000002"),
"buyers": [
{}
],
"content": "content book 3",
"title": "title book 3"
},
{
"_id": ObjectId("5a934e000102030405000001"),
"buyers": [
{}
],
"content": "content book 2",
"title": "title book 2"
}
]
The result that I expected:
[
{
"_id": ObjectId("5a934e000102030405000000"),
"buyers": [
{
"_id": ObjectId("5a934e000102030405000003"),
"buyer": {
"_id": ObjectId("5a934e000102030405000004"),
"display_name": "Phineas",
"user_id": "123"
},
"post_id": 1,
"user_id": "123"
}
],
"content": "content book 1",
"title": "title book 1"
},
{
"_id": ObjectId("5a934e000102030405000002"),
"buyers": [],
"content": "content book 3",
"title": "title book 3"
},
{
"_id": ObjectId("5a934e000102030405000001"),
"buyers": [],
"content": "content book 2",
"title": "title book 2"
}
]
Now you can see my code in the Mongo playground link:
https://mongoplayground.net/p/qiC7FySejxF
Comparing your actual output and MongoDB Playground link, I believe that you miss out the $unset stage.
{
$unset: "buyers.buyers"
}
While after the $unset stage, you can add $set stage to update the buyers field by filtering the document which is not empty document via $filter.
{
$set: {
buyers: {
$filter: {
input: "$buyers",
cond: {
$ne: [
"$$this",
{}
]
}
}
}
}
}
Demo # Mongo Playground

How to find data based on sub-field name in MongoDB using Mongoose?

There is a sub-field called 'name' in MongoDB Collection (User):
[
{
"teacher": {
"name": "Alex",
"email": "alex#domain.com"
},
"waiter": {
"name": "Feliks",
"email": "feliks#domain.com"
},
"pilot": [
{
"name": "Sam",
"email": "sam#domain.com"
},
{
"name": "alice",
"email": "alice#domain.com"
}
],
},
{
"teacher": {
"name": "max",
"email": "max#domain.com"
},
"waiter": {
"name": "Sam",
"email": "sam#domain.com"
},
"pilot": [
{
"name": "richard",
"email": "richard#domain.com"
},
{
"name": "alice",
"email": "alice#domain.com"
}
],
}
]
How can I find data based on the field 'name'. For example, when I'm looking for 'Sam', it should return me the all documents since 'Sam' is in "waiter" and "pilot" in first and second documents respectively.
I cannot do something like:
User.find({"teacher.name": "Sam", "waiter.name": "Sam", "pilot.name": "Sam" })
This will return me nothing as it is an AND logic. What I need is an OR logic.
You can use the $or operator.
So the query should look like this:
User.find({ $or: [
{ "teacher.name": "Sam" },
{ "waiter.name": "Sam" },
{ "pilot.name": "Sam" }
]
});
Read here for me details.

Mongoose: Update of array inside another nested array element not working as expected

Here is my mongo schema:
{
"_id": ObjectId("5f8af2fc5f23667adf3bbaf2"),
"score": 2.5,
"questions": [{
"_id": ObjectId("5f8af30d5f23667adf3bbaf5"),
"desc": "some text",
},
{
"_id": ObjectId("5f8af3115f23667adf3bbaf8"),
"desc": "some text",
"options": [{
"_id": ObjectId("5f8af3115f23667adf3bbaf9"),
"name": "some name",
"desc": "description 1"
},
{
"_id": ObjectId("5f8af3115f23667adf3bbafa"),
"name": "some name",
"desc": "description 2"
}
]
}
]
}
I've to update the name and desc of the option having id as 5f8af3115f23667adf3bbaf9 which is in the one of the array elements of the question attribute having id as 5f8af30d5f23667adf3bbaf5 which is again part of the data having id as 5f8af2fc5f23667adf3bbaf2
Tried the following query which is getting executed successfully but not updating the option:
Model.findOneAndUpdate({
_id : ObjectId("5f8af2fc5f23667adf3bbaf2"),
"questions._id": ObjectId("5f8af30d5f23667adf3bbaf5"),
"questions.options._id": ObjectId("5f8af3115f23667adf3bbaf9"),
}, {
$set: {
"questions.$[q].options.$[o].order": data.order,
"questions.$[q].options.$[o].definition": data.definition,
"questions.$[q].options.$[o].type": data.type,
},
},
{
arrayFilters: [{ "q._id": ObjectId(qid) }, { "o._id": ObjectId(oid) }]
})
Is tihs possible to do in a single mongoose findOneAndUpdate method?
Your query is correct, I have just hardcoded object id values in array filter and it is updating the documents. I have updated name and desc as u said. Do try this out. One more thing in mongoose u have to specify the object id as "mongoose.Types.ObjectId".
Therefore in your case it would be like "q._id": mongoose.Types.ObjectId("5f8af3115f23667adf3bbaf8").
And one more thing is that you are using findAndUpdate, try using update only depending on your mongoose version
Here is mongoplayground:
https://mongoplayground.net/p/TP5iCTAC5R_
Query:
db.collection.update({
_id: ObjectId("5f8af2fc5f23667adf3bbaf2"),
"questions._id": ObjectId("5f8af3115f23667adf3bbaf8"),
"questions.options._id": ObjectId("5f8af3115f23667adf3bbaf9")
},
{
$set: {
"questions.$[q].options.$[o].name": "anotherName",
"questions.$[q].options.$[o].desc": "anotherDesc"
}
},
{
arrayFilters: [
{
"q._id": ObjectId("5f8af3115f23667adf3bbaf8")
},
{
"o._id": ObjectId("5f8af3115f23667adf3bbaf9")
}
]
})
Output :
[
{
"_id": ObjectId("5f8af2fc5f23667adf3bbaf2"),
"questions": [
{
"_id": ObjectId("5f8af30d5f23667adf3bbaf5"),
"desc": "some text"
},
{
"_id": ObjectId("5f8af3115f23667adf3bbaf8"),
"desc": "some text",
"options": [
{
"_id": ObjectId("5f8af3115f23667adf3bbaf9"),
"desc": "anotherDesc",
"name": "anotherName"
},
{
"_id": ObjectId("5f8af3115f23667adf3bbafa"),
"desc": "description 2",
"name": "some name"
}
]
}
],
"score": 2.5
}
]

Mongoose aggregate group items by tag

I'm trying to group items by tag. But I do not get what exactly I want to do.
There is schema Item (_id, name, tags) with tags is array of tags_id ( was referenced from Tag schema )
Item = new Schema({
id: Schema.ObjectId,
name: String,
tags: [ { type: Schema.ObjectId, ref: 'Tag' }]
});
Tag = new Schema({
id: Schema.ObjectId,
name: String
});
This is what I have done so far:
Item.aggregate([
{
"$lookup": {
"from": Tag.collection.name,
"let": { "tags": "$tags" },
"pipeline": [
{
"$match": {
"$expr": { "$in": ['$_id', '$$tags'] }
}
},
{
"$project": {
"_id": 1,
"name": 1
}
}
],
"as": 'tags'
}
},
{
"$group": {
"_id": "$tags._id",
"items": {
"$push": {
"id": "$_id",
"name": "$name",
}
}
}
}
]);
This is what I get
{
"data": [
{
"_id": [
"5eb95e8dcae79713f1de0a27"
],
"items": [
{
"id": "5eb95e9fcae79713f1de0a28",
"name": "My Item 1"
}
]
},
{
"_id": [
"5eb9564dc4317411fe79e1bf"
],
"items": [
{
"id": "5eb95b1430f138131ed90f4f",
"name": "My Item 2"
},
{
"id": "5eb95ed0cae79713f1de0a29",
"name": "My Item 3"
}
]
}
]
}
I would like to get the name of each tag, and not only the _id possibly not within an array. Below the result that I would like to receive:
{
"data": [
{
"_id": "5eb95e8dcae79713f1de0a27",
"name": "My Tag name 1",
"items": [
{
"id": "5eb95e9fcae79713f1de0a28",
"name": "My Item 1"
}
]
},
{
"_id": "5eb9564dc4317411fe79e1bf",
"name": "My Tag name 2",
"items": [
{
"id": "5eb95b1430f138131ed90f4f",
"name": "My Item 2"
},
{
"id": "5eb95ed0cae79713f1de0a29",
"name": "My Item 3"
}
]
}
]
}
What am I doing wrong?
One way to to this is to add the tag-name to your $group operator:
...
{
"$group": {
"_id": "$tags._id",
"tagName": {$first: "$tags.name"},
"items": {
"$push": {
"id": "$_id",
"name": "$name",
}
}
}
}
...
Note that this will take the first matching entry for each group. Another option would be to use $replaceRoot and the $mergeObjects operator, like it was done here.

How can I update one document at nested array

{
"_id": "5e28b029a0c8263a8a56980a",
"name": "Recruiter",
"data": [
{
"_id": "5e28b0980f89ba3c0782828f",
"targetLink": "https://www.linkedin.com/in/dan-kelsall-7aa0926b/",
"name": "Dan Kelsall",
"headline": "Content Marketing & Copywriting",
"actions": [
{
"result": 1,
"name": "VISIT"
},
{
"result": 1,
"name": "FOLLOW"
}
]
},
{
"_id": "5e28b0980f89ba3c078283426f",
"targetLink": "https://www.linkedin.com/in/56wergwer/",
"name": "56wergwer",
"headline": "asdgawehethre",
"actions": [
{
"result": 1,
"name": "VISIT"
}
]
}
]
}
Here is one of my mongodb document. I'd like to update data->actions->result
So this is what I've done
Campaign.updateOne({
'data.targetLink': "https://www.linkedin.com/in/dan-kelsall-7aa0926b/",
'data.actions.name': "Follow"
}, {$set: {'data.$.actions.result': 0}})
But it seems not updating anything and even it can't find the document by this 'data.actions.name'
You need the positional filtered operator since the regular positional operator ($) can only be used for one level of nested arrays:
Campaign.updateOne(
{ "_id": "5e28b029a0c8263a8a56980a", "data.targetLink": "https://www.linkedin.com/in/dan-kelsall-7aa0926b/" },
{ $set: { "data.$.actions.$[action].result": 0 } },
{ arrayFilters: [ { "action.name": "Follow" } ] }
)

Resources