Updating embedded document in MongoDB - mongodb

My documents are structured as follows:
{_id: 1, country: 'USA', names: [{language: 'en', name: 'New York', state:'new'}, {language: 'es', name: 'Nueva York', state:'translated'}]}
{_id: 2, country: 'France', names: [{language: 'en', name: 'Paris', state:'new'}, {language: 'it', name: 'Parigi', state:'translated'}]}
...
I want to update the state of an item for a specific language, and if the language does not exist, to add the corresponding embedded document. For example, I would want to update item 1 to set state='new' for language='es' because that language exists:
{_id: 1, country: 'USA', names: [{language: 'en', name: 'New York', state:'new'}, {language: 'es', name: 'Nueva York', state:'translated'}]}
And I would want to add an embedded document to item 2 with state='new' and language='fr' because it doesn't exist:
{_id: 2, country: 'France', names: [{language: 'en', name: 'Paris', state:'new'}, {language: 'it', name: 'Parigi', state:'translated'}, {language: 'fr', name: 'Paris', state:'new'}]}
How can I do that?
Thanks.

You need to use The $ positional operator. See http://www.mongodb.org/display/DOCS/Updating#Updating-The%24positionaloperator for more.
In your case it will be
db.cities.update({'_id':1,'names.language':'es'},{$set:{'names.$.state':'new'}});

Related

How to get a field of an object in document?

I am not sure how to phrase this question properly but basically I have an "Order" Schema and each order model contains an array of product objects created using "Product" Schema
When I create an order, my req.body is this
body: {
orderItems: [ [Object] ],
shippingAddress: {
fullName: '123',
address: '1231',
city: '123',
postalCode: '123',
country: '123'
},
shippingPrice: 0,
paymentMethod: 'Stripe',
itemsPrice: 338,
totalPrice: 338
},
If I log req.body.orderItems, I can see each product object printed
{
_id: new ObjectId("62d51a3895cad3ca283302f3"),
name: 'Christmas Cake',
slug: 'christmas-cake',
image: '/images/cake.jpg',
shop: 'Custom Cakes',
category: 'food',
description: 'Custom baked christmas cake, pre-order needed.',
price: 70,
stock: 1,
rating: 3,
numReviews: 2,
__v: 2,
createdAt: 2022-07-18T08:30:48.931Z,
updatedAt: 2022-07-20T03:03:00.592Z,
}
{
_id: new ObjectId("62d7a8c126dcacfc13055e3d"),
name: 'cake',
slug: 'cake',
image: '/images/cake.jpg',
shop: 'Custom Cakes',
category: 'food',
description: 'cake',
price: 15,
stock: 2,
rating: 0,
numReviews: 0,
user: { _id: new ObjectId("62d51d57c08cd7e6675e8d45")},
reviews: [],
createdAt: 2022-07-20T07:03:29.372Z,
updatedAt: 2022-07-20T07:03:59.315Z,
__v: 0
}
But I am unable to obtain the 'shop' field. req.body.orderItems.shop returns undefined

MongoDB schema and structure

I just started learning mongoDB and mongoose here.
Is it possible to have value as key in mongoDB? For example, I'd like to have a structure like this:
Person collection:
USA: {
'John Doe': { phone: '...', somethingElse: '...' },
'Jane Doe': { phone: '...', somethingElse: '...' },
},
Australia: {
'John Doe': { phone: '...', somethingElse: '...' },
'Jane Doe': { phone: '...', somethingElse: '...' },
},
England: {
'John Doe': { phone: '...', somethingElse: '...' },
'Jane Doe': { phone: '...', somethingElse: '...' },
}
I know it's a terrible example, and I understand alternatively we can store the documents like:
{_id: 1, name: 'John Doe', address: 'USA', phone: '...', ...},
{_id: 2, name: 'John Doe', address: 'Australia', phone: '...', ...},
{_id: 3, name: 'John Doe', address: 'England', phone: '...', ...},
I guess I'm just trying to understand if storing value as key is even possible here. And if it is, how do we define the schema with mongoose?
Theoretically you could use a schema like:
const testSchema = new Schema({
countries: {
type: Map,
of: {
type: Map,
of: Object,
},
},
});
taking advantage of Map type in mongoose, then you can assign your dynamic object to contries property.
Personally I believe that second approach you mentioned is a way better idea (unless you really have a good reason for using the first one).
First reason is that having dynamic key names makes querying difficult. Instead of simple .find({name: 'John Doe'}) you need to run complicated aggregation queries like here. Basically any traversing like counting people, filtering by phone etc will be painful with dynamic keys.
Second reason is that MongoDB document has 16MB limitation so gathering too many people means you can approach that limit.

How to set updated object in first position - Mongo DB? [duplicate]

This question already has answers here:
MongoDB field order and document position change after update
(8 answers)
Closed 5 years ago.
I have this object and query
Object
{
_id: 1,
name: 'John Smith',
items: [{
name: 'item 1',
value: 'one',
_id: 1
},{
name: 'item 2'
value: 'two',
_id: 2,
}]
}
Query
Person.update({'items._id': 2}, {'$set': {
'items.$.surname': 'new surname'
}}, function(err) { ...
I want that the new updated (key / value) to be setted on first position like this
,{
surname: 'new surname',
name: 'item 2'
value: 'two',
_id: 2,
}
not like this
,{
name: 'item 2',
value: 'two',
_id: 2,
surname: 'new surname',
}
So is there a solution,
Thanks in advance
As far as I know if you append a property to an object that wasn't previously there it will always be appended to the object. The only workaround is to set the surname in the object to start with.

How to retrieve all the possible nested keys of all documents of a mongodb collection

I would like to retrieve the names of all the nested keys present in all the documents in a given mongodb collection.
E.g.:
> db.sample.insert({account: 'abc', account_type: 'individual', properties:
{title: 'mr', gender: 'M', dob: '19850101' }});
> db.sample.insert({account: 'xyz', account_type: 'individual', properties:
{title: 'ms', gender: 'F' }});
> db.sample.insert({account:'lmn', account_type: 'business', properties:
{title: 'messrs', industry: 'telecom', estd_on: '19850301' }});
I would like to get the unique keys (including all the nested keys) like:
[account, account_type, properties.title, properties.gender,
properties.dob, properties.industry, properties.estd_on]

Find several items in one search with MongoDB

I have a Users Collection and a Rooms Collection, the rooms collection stores references to the user id of the users in the room.
users = [
{_id:1, name: 'name 1', type: 1},
{_id:2, name: 'name 2', type: 1},
{_id:3, name: 'name 3', type: 1},
{_id:4, name: 'name 4', type: 1}
];
room = {
name: 'example room',
connected_users: [
{user_id: '2', admin: false},
{user_id: '3', admin: true}
]
};
Is there a way to search in the Users collection for the details of the connected users like this or similar?
db.users.find({_id: [2,3]});
That returns
[{_id:2, name: 'name 2', type: 1}, {_id:3, name: 'name 3', type: 1}]
That's what the $in operator is for:
db.users.find({_id: {$in: [2,3]}});
db.Users.find({_id: {$in: [2,3]}}).toArray();