mongoDB: Can't add an field to an array object - javascript

This is how my db document looks like:
{
"_id" : "aN2jGuR2rSzDx87LB",
"content" : {
"en" : [
{
"content" : "Item 1",
"timestamp" : 1518811796
}
]
}
}
Now I need to add another field in the first object of the content.en array.
The document itself gets selected by an ID.
The result should be:
{
"_id" : "aN2jGuR2rSzDx87LB",
"content" : {
"en" : [
{
"content" : "Item 1",
"timestamp" : 1518811796,
"user" : {
"id" : 'userId'
}
}
]
}
}
I tried to do it like this, but nothing is happening. I don't even get an error message.
Content.update(
{ _id: id },
{
$addToSet: {
'content.en.0.user': {
id: 'userId',
}
}
}
)
Also I would like to use an variable for the language. How do I do that? Something like 'content.' + language + '.0.user'...

$addToSet is useful when you want to add someting to an array. In your case you want to modify first element of your array (at index 0) so you should simply use $set (which is field update operator):
Content.update(
{ _id: "aN2jGuR2rSzDx87LB" },
{
$set: {
"content.en.0.user": {
id: "userId",
}
}
}
)

Related

How to filter out text fields in a complex query?

I've got a lot of doc filters on my UI (date ranges, checkboxes, input fields), so the query is generated dynamically - that's why I decided to create a boolean query, and push everything to must array. This is the example of my request:
const {
body: {
hits
}
} = await esclient.search({
from: filterQuery.page || 0,
size: filterQuery.limit || 1000,
index,
body: query
});
Checkboxes (I used additional bool.should inside must array) and date range work perfectly, but term/match filtering is not working at all:
{
"query": {
"bool": {
"must": [
{"match": { "issueNumber": "TEST-10" }}
]
}
}
}
The query above gives me all the documents from the index that contains "TEST" (with their scores), if I change match to term - it returns an empty array.
As my field is of a type 'text', I've also tried filter query - ES still gives all the documents with 'TEST' word:
{
"query": {
"bool": {
"must": [
{
"bool": {
"filter": {
"match": {"issueNumber": "TEST-10"}
}
}
}
]
}
}
}
This is how my hit looks like:
{
"_index" : "test_elastic",
"_type" : "_doc",
"_id" : "bj213hj2gghg213",
"_score" : 0.0,
"_source" : {
"date" : "2019-11-26T13:27:01.586Z",
"country" : "US",
"issueNumber" : "TEST-10",
}
Can someone give me input on how to filter the docs properly in complex query?
This is the structure of my index:
{
"test_elasticsearch" : {
"aliases" : { },
"mappings" : {
"properties" : {
"country" : {
"type" : "text"
},
"date" : {
"type" : "date"
},
"issueNumber" : {
"type" : "text"
}
}
},
"settings" : {
"index" : {
"creation_date" : "1574759226800",
"number_of_shards" : "1",
"number_of_replicas" : "1",
"uuid" : "PTDsdadasd-ERERER",
"version" : {
"created" : "7040299"
},
"provided_name" : "logs"
}
}
}
}
Ok, the problem is that your issueNumber field has not the right type, it should be keyword instead of text if your goal is to make exact searches on it. Same for country. Modify your mapping like this:
"properties" : {
"country" : {
"type" : "keyword"
},
"date" : {
"type" : "date"
},
"issueNumber" : {
"type" : "keyword"
}
}
Then reindex your data and your queries will work.

Simplify forEach statement to update a mongoDB document with nested objects and arrays

I'd like to update the value of the key shouldSendAlert in the following document:
{
"_id" : ObjectId("5c61c4db46d18e1092c5b024"),
"service" : "SRVPVD",
"menu" : [
{
"sub" : [
{
"options" : [
{
"item" : [
{
"name" : "",
"actions" : [
{
"name" : "communicateClient",
"value" : true
},
{
"name" : "shouldSendAlert",
"value" : false
}
]
}
],
"name" : "Technology Support"
},
{
"item" : [
{
"name" : "",
"actions" : [
{
"name" : "communicateClient",
"value" : true
}
]
}
],
"name" : "Company Support"
}
],
"name" : "Support"
},
{
"name" : " FAQ"
}
],
"name" : "Help"
}
]
}
I've managed to do this, querying the document using a multiple $elemMatch query, and using forEach to run through the nested arrays in order to alter the value of shouldSendAlert:
{
let menuItems = db.getCollection('menumodels').find({menu: {$elemMatch: {name: 'Help',sub: {$elemMatch: {name: 'Support',motivos: {$elemMatch: {name: 'Technology Support'}}}}}}});
menuItems.forEach((r) => {
r.menu.forEach(menuItem => {
if (menuItem.name == 'Help') {
menuItem.sub.forEach(sub => {
if (sub.name == 'Support') {
sub.motivos.forEach(motivo => {
if (motivo.name == "Technology Support") {
motivo.item[0].actions.forEach(action => {
if (action.name == 'shouldSendAlert') {
action.value = true;
db.getCollection('menumodels').update({_id: r._id}, {$set: {menu: r.menu}})
}
})
}
})
}
})
}
})
});
}
Is it - regarding performance - necessary, to code this MongoDB query
or update logic into a smarter form? Does the multiple use of $elemMatch affect performance?

Updating array inside two object in mongod

I have a collection of the structure as follows:
collection name : "positions"
Structure
{
"_id" : "vtQ3tFXg8THF3TNBc",
"candidatesActions" : {
"sourced" : [ ],
},
"appFormObject" : {
"name" : "✶ mandatory",
"questions" : [
{
"qusId" : "qs-585494",
"type" : "simple",
"qus" : "Which was your previous company"
},
{
"qusId" : "qs-867766",
"type" : "yesNo",
"qus" : "Are you willing to relocate?",
"disqualify" : "true"
}
]
}
}
I want to update "qus" field of the above collection whose _id is "vtQ3tFXg8THF3TNBc" and "qusId" is "qs-585494".
Try following....
db.positions.update(
{_id: "vtQ3tFXg8THF3TNBc", "appFormObject.questions.qusId":"qs-585494"},
{$set:{"appFormObject.questions.$.qus": "this is updated value"}}
)
Use following query
db.positions.findAndModify({
query: { _id: "vtQ3tFXg8THF3TNBc", "appFormObject.questions.qusId":"qs-585494"} ,
update: { $set: { 'appFormObject.questions.$.qus': 'Brilliant Green' } },
});
Thanks

MongoDB Aggregate - Unwind, group and project

Using the collection Users, is it possible to retrieve the below unique list of organisations/owners? If this current set up isn't possible, is it possible to get the same results from two ID-linked collections with one query?
Currently, using Mongoose I can only retrieve the group of organisation names:
Current query
userModel.aggregate([
{ $unwind:'$organisations' }
, { $group: { name: '$organisations.name' } }
])
Users
{ "_id" : ObjectId("53f4a94e7c88310000000001"),
"email" : "bob#example.com",
"organisations" : [
{
"name" : "OrgOne",
"isOwner" : true
}
]
},
{ "_id" : ObjectId("53f4a94e7c88310000000002"),
"email" : "ash#something.com",
"organisations" : [
{
"name" : "OrgOne"
}
]
},
{ "_id" : ObjectId("53f4a94e7c88310000000003"),
"email" : "george#hello.com",
"organisations" : [
{
"name" : "OrgTwo",
"isOwner" : true
}
]
}
Results
{ "orgName" : "OrgOne",
"owner" : 53f4a94e7c88310000000001
},
{ "orgName" : "OrgTwo",
"owner" : 53f4a94e7c88310000000003
}
Thanks in advance, Nick
Seems like an odd use of aggregation to me, but possibly there are several "organisations" per user here, so I guess I'll continue:
userModel.aggregate(
[
{ "$match": { "organisations.isOwner": true } },
{ "$unwind": "$organisations" },
{ "$match": { "organisations.isOwner": true } },
{ "$group": {
"_id": "$organisations.name",
"owner": { "$first": "$_id" }
}}
],
function(err,result) {
}
);
If there is more than one owner and you need some precedence then you can implement a $sort before the group. Or otherwise just $project rather than group in order to get everyone.

How to push new items to an array inside of an object

My JSON currently looks like this:
{
"_id" : 393,
"item" : 34,
"comments" : [
{
"name" : "kevin",
"messages" : [
"item",
"item"
]
},
{
"name" : "ryan",
"messages" : [
"item",
"item"
]
}
]
}
How could I push new items onto the messages array for the first or second item in the comments array?
db.newcon.update({_id: 393}, { $push: { comments['kevin']: {messages: 39 } } })
Using $elemMatch and $ operator you can update your documents check below query :
db.collectionName.update({"_id":393,"comments":{"$elemMatch":{"name":"kevin"}}},
{"$push":{"comments.$.messages":39}})
Something like this will work:
var newMessage = '39';
comments.forEach(function(item) {
if (item.name === 'kevin') {
item.comments.push(newMessage);
}
});

Categories

Resources