MongoDB: replace full object in array [duplicate] - mongodb

This question already has answers here:
How do I update Array Elements matching criteria in a MongoDB document?
(2 answers)
How to update a subdocument in mongodb
(1 answer)
Closed 5 years ago.
I was looking through StackOverflow, but most of the questions are related to updating of a single element of the object from the array.
In my case, I have a little different situation.
I want to replace full object from an array with a new one.
The original collection looks like:
db.countries.find().pretty()
{
"_id": "some ID goes here",
"longitude": "some longitude",
"latitude": "some latitude",
"name": "name of some country",
"millionaires": [
{"millionaire_id": "ID of the first millionaire",
"name": "name of the first millionaire",
"money": 12000000,
},
{"millionaire_id": "ID of the second millionaire",
"name": "name of the second millionaire",
"money": 15000000,
},
],
}
Then for some reason, I want to replace some data for the first millionaire(amount of money changed, etc.). NOTE: I don't know which field changed.
I'm trying to do something like this:
db.countries.update({"_id": "country ID",
"millionaires.millionaire_id": "ID of the first millionaire"
},
{$set: {
"millionaire_id": "the same millionaire ID",
"value": "should be another value", ...
}
})
But that works unexpectedly:
db.countries.find().pretty();
{
"_id": "some ID goes here",
"longitude": "some longitude",
"latitude": "some latitude",
"name": "name of some country",
"millionaires": [
{"millionaire_id": "ID of the first millionaire",
"name": "name of the first millionaire",
"money": 12000000,
},
{"millionaire_id": "ID of the second millionaire",
"name": "name of the second millionaire",
"money": 15000000,
},
],
{
"millionaire_id": "the same millionaire ID",
"value": "should be another value", ...
}
}
So, it added a new object out of my list of millionaires.
NOTE: objects for updates go programmatically that's why it's not a good idea to try something like this:
new_object = {"millionaires. millionaire_id": "ID", "millionaires.name": "name", ...}
I have raw objects and want to update existing elements using this objects.
Any ideas?

Related

Check for value in json array

I have a table of data which has a field called details which contains a json object.
The object looks something like this:
{
"name": "Persons Name",
"list": [
{
"name": "Persons Name",
"assigned": {
"company": "Company 1",
"number": "AA1"
}
},
{
"name": "Persons Name",
"assigned": {
"company": "Company 2",
"number": "BB2"
}
},
{
"name": "Persons Name",
"assigned": {
"company": "Company 3",
"number": "AA3"
}
}
],
"total_results": 3
}
Essentially, I want to return all data if any of the person's 'assigned'->>'number' field begins with an A. In the above example, two of the individuals numbers are prefixed with an A so I want all data returned.
I've been playing around and had have been making some progress but can't figure out how to bring it all together.
select f->'assigned'->>'number' from jsonb_array_elements((select details->'list' from table_name)) f;
The above query can get me a list of the three 'number' fields but I'm not sure how I can combine that with a query to return all the information, if any of these fields contain a prefix A
You are so close. Just add your condition in where clause.
SELECT *
FROM JSON_ARRAY_ELEMENTS((SELECT details -> 'list' FROM TABLE_NAME)) f
WHERE f -> 'assigned' ->> 'number' LIKE 'A%'
CHECK DEMO HERE

Is there any ways in mongodb acts like SQL "drop column"?

I have some mongodb documents which structure like:
{
"_id": ObjectId("58c212b06ca3472b902f9fdb"),
"Auction name": "Building",
"Estimated price": "23,660,000",
"Auction result": "success",
"Url": "https://someurl.htm",
"match_id": "someid",
"Final price": "17,750,000",
"Area": [
{
"Area": "696.77"
}
]
}
The "match_id" is used for update query and after that I don't need this entry anymore.
Is there any idea to drop this entry and keep the rest of the document?
Have you tried simpily using an update query to unset the field like the following
db.products.update(
{},
{ $unset: { match_id: "" } }
)
Keep in mind that the first set of curly braces has been intentionally left blank so that your update query matches every entry in your collection

How can I query an indexed object list in mongodb?

I have some documents in the "company" collection structured this way :
[
{
"company_name": "Company 1",
"contacts": {
"main": {
"email": "main#company1.com",
"name": "Mainuser"
},
"store1": {
"email": "store1#company1.com",
"name": "Store1 user"
},
"store2": {
"email": "store2#company1.com",
"name": "Store2 user"
}
}
},
{
"company_name": "Company 2",
"contacts": {
"main": {
"email": "main#company2.com",
"name": "Mainuser"
},
"store1": {
"email": "store1#company2.com",
"name": "Store1 user"
},
"store2": {
"email": "store2#company2.com",
"name": "Store2 user"
}
}
}
]
I'm trying to retrieve the doc that have store1#company2.com as a contact but cannot find how to query a specific value of a specific propertie of an "indexed" list of objects.
My feeling is that the contacts lists should not not be indexed resulting in the following structure :
{
"company_name": "Company 1",
"contacts": [
{
"email": "main#company1.com",
"name": "Mainuser",
"label": "main"
},
{
"email": "store1#company1.com",
"name": "Store1 user",
"label": "store1"
},
{
"email": "store2#company1.com",
"name": "Store2 user",
"label": "store2"
}
]
}
This way I can retrieve matching documents through the following request :
db.company.find({"contacts.email":"main#company1.com"})
But is there anyway to do a similar request on document using the previous structure ?
Thanks a lot for your answers!
P.S. : same question for documents structured this way :
{
"company_name": "Company 1",
"contacts": {
"0": {
"email": "main#company1.com",
"name": "Mainuser"
},
"4": {
"email": "store1#company1.com",
"name": "Store1 user"
},
"1": {
"email": "store2#company1.com",
"name": "Store2 user"
}
}
}
Short answer: yes, they can be queried but it's probably not what you want and it's not going to be really efficient.
The document structure in the first and third block is basically the same - you have an embedded document. The only difference between are the name of the keys in the contacts object.
To query document with that kind of structure you will have to do a query like this:
db.company.find({ $or : [
{"contacts.main.email":"main#company1.com"},
{"contacts.store1.email":"main#company1.com"},
{"contacts.store2.email":"main#company1.com"}
]});
This query will not be efficient, especially if you have a lot of keys in the contacts object. Also, creating a query will be unnecessarily difficult and error prone.
The second document structure, with an array of embedded objects, is optimal. You can create a multikey index on the contacts array which will make your query faster. The bonus is that you can use a short and simple query.
I think the easiest is really to shape your document using the structure describe in your 2nd example : (I have not fixed the JSON)
{
"company_name": "Company 1",
"contacts":{[
{"email":"main#company1.com","name":"Mainuser", "label": "main", ...}
{"email":"store1#company1.com","name":"Store1 user", "label": "store1",...}
{"email":"store2#company1.com","name":"Store2 user", "label": "store2",...}
]}
}
like that you can easily query on email independently of the "label".
So if you really want to use the other structure, (but you need to fix the JSON too) you will have to write more complex code/aggregation pipeline, since we do not know the name and number of attributes when querying the system. Theses structures are also probably hard to use by the developers independently of MongoDB queries.
Since it was not clear let me show what I have in mind
db.company.save(
{
"company_name": "Company 1",
"contacts":[
{"email":"main#company1.com","name":"Mainuser", "label": "main"},
{"email":"store1#company1.com","name":"Store1 user", "label": "store1"},
{"email":"store2#company1.com","name":"Store2 user", "label": "store2"}
]
}
);
db.company.save(
{
"company_name": "Company 2",
"contacts":[
{"email":"main#company2.com","name":"Mainuser", "label": "main"},
{"email":"store1#company2.com","name":"Store1 user", "label": "store1"},
{"email":"store2#company2.com","name":"Store2 user", "label": "store2"}
]
}
);
db.company.ensureIndex( { "contacts.email" : 1 } );
db.company.find( { "contacts.email" : "store1#company2.com" } );
This allows you to store many emails, and query with an index.

Update Mongodb collection record without retaining fields that not on the new record

Is there a way in Mongodb to update a record and drop fields that doesn't exist in updated version?
Like an existing record is:
{
"id": "helloworld",
"icon": "globe",
"title": "Hello World!",
}
When updated with this it looks like it did not update because it's not dropping "icon".
{
"id": "helloworld",
"title": "Hello World!",
}
The only option that I can think of is deleting the record and insert it again or figure out the fields that doesn't exist and use $unset.
I just want to find out if there's a better way to do what I want in Mongodb.
The update method can also completely replace a document if the update document only contains field:value pairs (instead of using update operators such as $set)
For an example,
> db.world.insert( {
"id": "helloworld",
"icon": "globe",
"title": "Hello World!",
} )
> db.world.update(
{ id: "helloworld" },
{ "id": "helloworld", title: "Hello World!" }
)
> db.world.find()
{ "_id" : ObjectId("5320e93b80b181227adb0e24"),
"id" : "helloworld",
"title" : "Hello World!"
}
For another example, you can also see
http://docs.mongodb.org/manual/reference/method/db.collection.update/#example-update-replace-fields
Hope this helps

How to query data from mongoDB which column is an array

{
"name": "Grieg And Sibelius Songs",
"status": 1,
"lastupdate": 1306294550,
"intro": "",
"artist": [
"ar9341cd00668311e0a45217d9fa59cf02",
"ar9341cd00668311e0a45217d9fa59cf0x"
],
"publisher": "(Warner Music)",
"release_date": "2006-05-08"
}
I want to find the the data that artist column "ar9341cd00668311e0a45217d9fa59cf02" in array("ar9341cd00668311e0a45217d9fa59cf02","ar9341cd00668311e0a45217d9fa59cf0d","ar9341cd00668311e0a45217d9fa59cf0r") what should I do?
You can use $exists to check the presence of the item in array,
db.yourcollectionname.find({artist: {$exists:'ar9341cd00668311e0a45217d9fa59cf02'}})