MongoDB check if key value exists and update only some fields - database

Let's say I have a MongoDB collection "people" that has the form
[
{
_id: [OBJECT_ID_1],
name: "Paul",
hobby: "rowing",
fixed: 1
},
{
_id: [OBJECT_ID_2],
name: "Selena",
hobby: "drawing",
fixed: 2
},
{
_id: [OBJECT_ID_3],
name: "Emily",
hobby: "jogging",
fixed: 3
}
]
And new data to be inserted of the form
var data = [
{
name: "Paul", // name exists, so keep "fixed" at 1
hobby: "archery",
fixed: 4
},
{
name: "Peter",
hobby: "knitting",
fixed: 5
}
]
I would like to insert/update the collection with the new data. However, if a document with the same "name" already exists, I do not want to update "fixed". The result after inserting the above data should be
[
{
_id: [OBJECT_ID_1],
name: "Paul",
hobby: "archery", // updated
fixed: 1 // not updated, because name existed
},
{
_id: [OBJECT_ID_2],
name: "Selena",
hobby: "drawing",
fixed: 2
},
{
_id: [OBJECT_ID_3],
name: "Emily",
hobby: "jogging",
fixed: 3
},
{ // newly inserted document
_id: [OBJECT_ID_4],
name: "Peter",
hobby: "knitting",
fixed: 5
}
]
The data includes a large number of documents, so I would like to achieve this in one query if possible. What would be the best way to accomplish this? Many thanks!

bulkWrite with updateOne's with $upsert:true seems to work best for you...

bulkWrite not perform a Find operation.
Its (in my case) is necessary to control if it will create a another document.
In my case I just use find check before insert/create method.
if (collection.find({"descr":descr}).limit(1).length === 1) {
//...create method
console.log('Exists')
}

Related

MongoDB Compass GROUP BY value

Lets say that i have the following objects in my mongodb-compass-database:
{
_id: ObjectID("randomString"),
Name: "Test1",
OtherAttribute: 187
},
{
_id: ObjectID("otherRandomString"),
Name: "Test2",
OtherAttribute: 1337
},
{
_id: ObjectID("otherRandomString2"),
Name: "Test1",
OtherAttribute: 23
}
How can I return the "Name"-value if it exist more than one time?
In the example I want to receive "Test1" or the whole object, doesnt matter.
I just need to see if there are any duplicates.
I need to use the MongoDB Compass Find-Input:
Is this possible?

MongoDB - Can't push an item to an array inside an object inside an array

I have this object in MongoDB:
{
_id: ObjectId("1"),
data: {
city: "ccp",
universities: [
{
_id: "2"
name: "universityOne"
students: []
},
{
_id: "3"
name: "universityTwo",
students: []
}
]
}
}
I need to push a Student object inside the students array inside the universityOne object inside the universities array, inside the global object.
I tried documentation and come up with this queries.
Mongo shell returns { "acknowledged" : true, "matchedCount" : 0, "modifiedCount" : 0 }. And nothing changes.
Here are the queries formatted/unformatted, so you can see them:
db.pautas.updateOne({_id: ObjectId("1")}, {$push: {"data.universities.$[id].students": {name: "aStudentName", age: 22}}}, {arrayFilters: [{"id._id": ObjectId("2")}]})
db.pautas.updateOne({_id: ObjectId("1")}, {$push: {"data.universities.$[id].students": {name: "aStudentName", age: 22}}}, {arrayFilters: [{"id._id": ObjectId("2")}]})
This second query is with the name of the university on the mongo [<identifier>]. But doesn't work either.
db.pautas.updateOne({_id: ObjectId("1")}, {$push: {"data.universities.$[name].students": {name: "aStudentName", age: 22}}}, {arrayFilters: [{"name.name": "universityOne"}]})
db.pautas.updateOne({_id: ObjectId("1")}, {$push: {"data.universities.$[name].students": {name: "aStudentName", age: 22}}}, {arrayFilters: [{"name.name": "universityOne"}]})
Regards.
UPDATE
Real object:
{
_id: ObjectId("5c6aef9bfc1a2693588827d9"),
datosAcademicos: {
internados: [
{
_id: ObjectId("5c6bfae98857df9f668ff2eb"),
pautas: []
},
{
_id: ObjectId("5c6c140f8857df9f668ff2ec"),
pautas: []
}
]
}
}
I need to add a Pauta to the pautas array. I've set pautas to an array of strings for debugging purpose, so just need to push a "hello world" or whatever string.
I tried this with the answers I've been given:
db.pautas.updateOne({"_id":ObjectId("5c6aef9bfc1a2693588827d9"), "datosAcademicos.internados._id": ObjectId("5c6bfae98857df9f668ff2eb")}, { $push: {"datosAcademicos.internados.$.pautas": "hi"}})
db.pautas.updateOne({"_id":ObjectId("5c6aef9bfc1a2693588827d9"), "datosAcademicos.internados._id": ObjectId("5c6bfae98857df9f668ff2eb")}, { $push: {"datosAcademicos.internados.$.pautas": "hi"}})
Update 2:
Mongo version: v4.0.2
Using Robo 3T.
I created a test database
And tried this command
Still not working.
There are 3 issues with your statement. First, the root ID field is "id" and you're querying the "_ID".
Second, you should put the match fields altogether. This update works as expected.
Third, you should use "$" to select the nested array position, not "$[id]".
db.pautas.updateOne(
{ "id": ObjectId("1"), "data.universities._id": "2"},
{$push:
{"data.universities.$.students": {name: "aStudentName", age: 22}}
})
Answer to the question UPDATE:
The update statement worked just fine.
Update statement
Record after update - I ran my update with your data and then the update code you posted, both worked just fine.

MongoDB update nested array elements

I have the following structure:
{
id: "1",
invoices: [{ id: "1", balance: 1},{ id: "2", balance: 1}]
},
{
id: "2",
invoices: [{ id: "3", balance: 1},{ id: "4", balance: 1}]
}
I'm getting a list of invoices IDs that i shouldn't update, the rest i need to update the balance to 0.
I'm pretty new to MongoDB and managing to find a way to do it.
Let say you want to update all invoices of id 1 except invoice.id 2 try this one:
db.collection.update(
{ id: "1", "invoices.id": {$ne: 2} },
{
$set: {
"invoices.$[]": { balance: 0 }
}
}
)
First of all, you forgot the quotes around the field names. Your documents should be like this:
{
"id": "1",
"invoices": [{
"id": "1",
"balance": 1
}, {
"id": "2",
"balance": 1
}]
}
I have limited experience with MongoDB, as I learnt it this semester at University. However, here is my solution:
db.collection.update(
{ id: "1" },
{
$set: {
"invoices.0": { id: "1", balance: 0 }
}
}
)
What does this solution do?
It takes the document with id 1. That is your first document.
The $set operator replaces the value of a field with the specified value. (straight out from the MongoDB manual - MongoDB Manual - $set operator).
"invoices.0" takes the first invoice from the invoices array and then it updates the balance to 100.
Replace the word collection from db.collection with your collection name.
Try and see if it works. If not, I'd like someone with more experience to correct me.
LE: Now it works, try and see.

how to merge similar values in normalizr function?

I have unusual response from server like this
[
{
id: 1,
name: "Alexandr",
children: [
{
id: 2,
name: "Stephan"
},
{
id: 3,
name: "Nick"
}
]
},
{
id: 4,
name: "David",
children: [
{
id: 3,
name: "Nick"
},
{
id: 6,
name: "Paul"
}
]
}
]
i would like to normalize this response to receive a diction with all people. So, i use normalizr go flat this
const people= new Schema('people');
people.define({
Children: arrayOf(people),
NotOwnChildren: arrayOf(people)
});
let normalized = normalize(response.data, arrayOf(people));
but doing like this i get an error
"When merging two people, found unequal data in their "Children" values. Using the earlier value."
How can i adjust normalizr to merge people with same id (update entities with newest data)?
It looks like you're getting two people that have differing values for one of their keys (I'm assuming your example input is truncated).
For Normalizr#2:
You can use a custom mergeIntoEntity function to resolve the issue manually.
For Normalizr#>=3.0.0, you'll need use mergeStrategy.

How to check before updating an array element in MongoDB/NodeJS

In my sample document, I have a campaign document that contains the _id of the document and an importData array. importData is an array of objects containing a unique date and source value.
My goal is to have an object updated with a unique date/source pair. I would like to have the new object replace any matching object. In the example below, Fred may have originally donated a TV, but I want my application to update the object to reflect he donated both a TV and a radio.
// Events (sample document)
{
"_id" : "Junky Joe's Jubilee",
"importData" : [
{
"date": "2015-05-31",
"source": "Fred",
"items": [
{item: "TV", value: 20.00},
{item: "radio", value: 5.34}
]
},
{
"date": "2015-05-31",
"source": "Mary",
"items": [
{item: "Dresser", value: 225.00}
]
}
]
}
My original thought was to do something like the code below, but not only am I updating importData with Fred's donations, I'm also blowing away anything else in the importData array:
var collection = db.collection("events");
collection.update(
{_id: "Junky Joe's Jubilee",
importData: {
date: "2015-05-31",
source: 'Fred'
},
}, // See if we can find a campaign object with this name
{
$set:
{"importData":
{
date: "2015-05-31",
source: 'Fred',
items: [
{item: "TV", value: 20.00},
{item: "radio", value: 5.34}
]
}
}
},
{upsert: true}); // Create a document if one does not exist for this campaign
When I tried pushing (instead of $set), I was getting multiple entries for the date/source combos (e.g. Fred would appear to have donated two items multiple times on "2015-05-31").
How would I go about doing that with the MongoDB native driver and NodeJS?
Try this
var collection = db.collection("events");
collection.update(
{_id: "Junky Joe's Jubilee",
importData: {
date: "2015-05-31",
source: 'Fred'
},
}, // See if we can find a campaign object with this name
{
$set:
{"importData.$":
{
date: "2015-05-31",
source: 'Fred',
items: [
{item: "TV", value: 20.00},
{item: "radio", value: 5.34}
]
}
}
},
{upsert: true}); // Create a document if one does not exist for this campaign
According to the documentation under Array update operators this should only modify the first element in the array, which matches the query.

Resources