How do I use upsert and $addToSet in conjunction? - node.js

I would like to insert a document that looks like this:
{
name: "app1",
theArray: [...unique string elements...]
}
I tried to do an upsert using the query below but it somehow creates an array within an array if the document does not exist. If I use $push when the document does not exist, then the array is created fine. However I need to use $addToSet to maintain array element uniqueness.
Current query:
collection1.upsert({
name: "app1",
}, {
$addToSet: {
theArray: data // data is an array of ip addresses eg. ["1.1.1", "2.2.2.2"] which is not unique
}
});
Executing the above query when there is no existing document in the db creates:
{
name: "app-1",
theArray: [
//another array that contains the actual data.
]
}
Is there a way I can get this behavior with just a single query?

Related

Update a value inside array of objects, inside a document in MongoDB

Here is what my collection looks like
Now suppose I have to update count of 2nd document whose reportTypes.reasonId is 300. I have access to _id as well as reasonId to update the count. I am using Mongoose to query things in my Node application.
What can I try to solve this?
You can do it via arrayFilters:
db.collection.update(
{
managerId:3
},
{
$inc:{"reportTypes.$[x].count":1}
},
{
arrayFilters:[{"x.reasonId":300 }]
}
)
playground
Explained:
Specify the matching document in the query part and create arrayFilter "x" matching the correct reportTYpes array subdocument , in the update part use the $inc operation to increment the count value in the example with 1
you should use dot notation and the $ update operator to do this:
(I'm assuming your collection is called Reason)
var conditions = {
'_id': '6244........',
'reasonTypes.reasonId': 300
}
var update = {
$inc: {
'reasonTypes.$.count': 1
}
};
Reason.update(conditions, update, function(err) {
// Handle error here
})
You can find more on the operator here mongo $ update operator

MongoDB update query in subarray

An update in the array of objects inside another array of objects.
mongodb field that I'm working on:
otherFields: values,
tasks: [
{
_id: mongodb.objectID(),
title: string,
items:[{
_id: mongodb.objectID(),
title: string,
completed: boolean //field need to be update.
}]
},
{}...
],
otherFields: value
sample mongodb document
I need to find the document using the task_id and the item_id and update a completed field in item of a task. Using the mongoose findOneAndUpdate method
const path = "tasks.$.items." + item_id + "completed";
collectionName.findOneAndUpdate(
{ _id: req.user._id, "tasks._id": taskID },
{ $set: { [path]: true }});
The above query doesn't work!!!
There is no need to use multiple query conditions, since you'd like to update a specific item that has an unique ID. Therefore you could use something along the lines:
collectionName.findOneAndUpdate(
{ 'tasks.items._id': itemID },
...
);
Keep in mind this structure is far away from optimized as it would basically look through the entire database...
Also now that I think of it, you'd also have issue with the update, as there are two nested arrays within the document. Read more here: How to Update Multiple Array Elements in mongodb

Insert a whole json Without creating different node in mongodb

i have a collection named drop down and i want to insert all the drop down static JSON values in a single collections without creating different node
for eg this is my json
"education": [
"Master",
"Bachelor"
],
"diet": [
"Veg",
"Non Veg"
]
Later on if i need to add more drop down values i don't have to alter the mongoose schema ,i could directly insert the json list
Is it possible or not? Sorry i am new to the Mongodb
Finally an idea strike on my mind and got the appropriate answer of my own question and like to share here. What i did is , I create the Schema as
const mongoose = require('mongoose');
const dropDownSchema = new mongoose.Schema({dropDown : mongoose.Schema.Types.Mixed})
module.exports.DropDownList =mongoose.model("DropDownList",dropDownSchema);
later on while passing data from the client
{
"dropDown":
{
"education": [
"Master"
,"Bachelor"
],
"diet": [
"Veg"
,"Non Veg"
]
}
}
While inserting data i first delete all data and insert the fresh one from the API
First find the document in that collection. Assume that we are requesting with the document _id and we are using mongoose model named Dropdown.
Example:
const document = await Dropdown.findOne({_id});
//Once you have found the document
// Add or change the existing fields
document[new_value_name] = new_values.map(val => val);
await document.save();
If you want to store it in array of object in mongodb then you can also create a schema with Array of dropdowns
var DropdownSchema = new mongoose.Schema({
dropdowns:[{
dropdown_key: { type: String },
dropdown_values: [{type: String}]
}]});
While inserting data you will need to loop through Object.keys of your json list and insert into as array . You can add number of dropdown as it is stored as array of object.
Please let me know if it helps.

DynamoDB update inside an array of objects (nodejs)

I noticed that DynamoDB can add and remove items from an array but how do you search for an specific item inside an object if you want to update that one specifically?
For example:
In MongoDB you can search for someitem.$.subitem and update that specific item.
Is there a way on how to do this with DynamoDB?
Item: {
someitem: [
{
subitem: "id",
somevalue: "something"
}
]
}
I would say this is basic functionality but seems not easy to find (or even unsupported)
AWS does not permit to modify it in a single update request more info was found in the following answers:
updating-a-json-array-in-aws-dynamodb.
The solution that they propose is to change the schema from array to {}, or to implement a custom functions and iterate through each array and find your new id to update, so to speak to programatically update your json and then insert whole object.
TableName : 'tablename',
Key : { id: id},
ReturnValues : 'ALL_NEW',
UpdateExpression : 'set someitem['+`index`+'].somevalue = :reply_content',
ExpressionAttributeValues : { ':reply_content' : updateddata }
array element edit via array index

Node.js and MongoDB if document exact match exists, ignore insert

I am maintaining a collection of unique values that has a companion collection that has instances of those values. The reason I have it that way is the companion collection has >10 million records where the unique values collection only add up to 100K and I use those values all over the place and do partial match lookups.
When I upload a csv file it is usually 10k to 500k records at a time that I insert into the companion collection. What is the best way to insert only values that dont already exist into the unique values collection?
Example:
//Insert large quantities of objects into mongo
var bulkInsert = [
{
name: "Some Name",
other: "zxy",
properties: "abc"
},
{
name: "Some Name",
other: "zxy",
properties: "abc"
},
{
name: "Other Name",
other: "zxy",
properties: "abc"
}]
//Need to insert only values that do not already exist in mongo unique values collection
var uniqueValues = [
{
name:"Some Name"
},
{
name:"Other Name"
}
]
EDIT
I tried creating a unique index on the field, but once it finds a duplicate in the Array of documents that I am inserting, it stops the whole process and doesnt proceed to check any values after the break.
Figured it out. If your doing it from the shell, you need to use Bulk() and create insert jobs like this:
var bulk = db.collection.initializeUnorderedBulkOp();
bulk.insert( { name: "1234567890a"} );
bulk.insert( { name: "1234567890b"} );
bulk.insert( { name: "1234567890"} );
bulk.execute();
and in node, the continueOnError flag works on a straight collection.insert()
collection.insert( [{name:"1234567890a"},{name:"1234567890c"}],{continueOnError:true}, function(err, doc){}
Well, I think the solution here is quite simple if I understand correctly your issue.
Since the process is stopped when it finds a duplicated field you should basically check if the value doesn't already exists before to try to add it.
So, for each element in uniqueValues, make a find/findOne query, if it doesn't return any result then add the element, otherwise don't.

Resources