MongoDB: Appending a nested array structure inside a nested array in mongoDB - mongodb

I have a collection in mongoDB containing many documents, One of which looks like,
{
date: '2012-10-20 12:30UTC',
personal_info: {name: 'sam', group_id: 'A1234', address:['rourkela', 'sundergarh']},
blog:[{ blog: 'Got admitted to IIT',
comments:[{
author:{name:'sam', email: 'sam#gmail.com'},
comment:'good buddy',
ph_no: 12345
},
{
author:{name:'vam', email: 'vam#gmail.com'},
comment:'happy for you',
ph_no:56789}
}]
}]
}
My requirement is to append a sub document like structure into the comments array where blog is 'Got admitted to IIT'
The Sub document I wand to append is given below:
{
author:{name:'mam', email: 'mam#gmail.com'},
comment:'great, keep it up'
}
My document structure after appending the structure above should look like:
{
date: '2012-10-20 12:30UTC',
personal_info: {name: 'sam', group_id: 'A1234', address:['rourkela', 'sundergarh']},
blog:[{ blog: 'Got admitted to IIT',
comments:[{
author:{name:'sam', email: 'sam#gmail.com'},
comment:'good buddy',
ph_no: 12345
},
{
author:{name:'vam', email: 'vam#gmail.com'},
comment:'happy for you',
ph_no:56789
},
{
author:{name:'mam', email: 'mam#gmail.com'},
comment:'great, keep it up'
}]
}]
}
How do I achieve the above by Coding in mongo shell.
Thanks in advance..

You can do it as follows :
db.myObject.update(
{"blog.blog" : "Got admitted to IIT"},
{
"$push" : {
"blog.$.comments" : {
author: {name:'mam', email: 'mam#gmail.com'},
comment:'great, keep it up'
}
}
}
)

Related

Getting directly an array from a mongoose model

I'm trying to query directly to an array inside of an mongoose document, but for the moment i have couldn't.
The document example:
{
_id:62141a799b646c7926fcfa9c
firstname:"firstname"
lastname:"lastname"
username:"username"
phone:"0000-0000000"
email:"Example#mail.com"
email_verified_at:null
password:"$2a$10$LUATvtyPmlojHVdCkxP/QO9UUzQgOoGCW6xyx8YPUZkt5l7j6kHxK"
remember_token:null
deleted_at:null
created_at:2022-02-21T23:04:25.097+00:00
updated_at:2022-02-21T23:04:25.097+00:00
notes: [
"621954b8f073154099b92fca"
"62142c426ca950e33baa1302"
]
I have a query that works but i think that isn't the most optimal approach, altough i could be wrong.
I want to get something like this:
[
"621954b8f073154099b92fca"
"62142c426ca950e33baa1302"
]
or populated:
[
{
_id: new ObjectId("621954b8f073154099b92fca"),
user: new ObjectId("62141a799b646c7926fcfa9c"),
type: new ObjectId("62076ce385b4eea8c5aeb8ba"),
title: 'qwasdasd',
content: '',
created_at: 2022-02-25T22:14:16.515Z,
updated_at: 2022-02-25T22:14:16.515Z
},
{
_id: new ObjectId("62142c426ca950e33baa1302"),
user: new ObjectId("62141a799b646c7926fcfa9c"),
type: new ObjectId("62076ce385b4eea8c5aeb8ba"),
title: 'qwasdasd',
content: '',
created_at: 2022-02-25T22:14:16.515Z,
updated_at: 2022-02-25T22:14:16.515Z
}
]
And even if i need to find an specific field, search it, but with the query:
const notes = await collection.findOne({ _id: '62141a799b646c7926fcfa9c', notes: { _id: '621954b8f073154099b92fca' } }, { 'notes.$._id': true });
i have this rersult:
{
_id: new ObjectId("62141a799b646c7926fcfa9c"),
notes: [
"621954b8f073154099b92fca"
]
}
or populated:
{
_id: new ObjectId("62141a799b646c7926fcfa9c"),
notes: [
{
_id: new ObjectId("621954b8f073154099b92fca"),
user: new ObjectId("62141a799b646c7926fcfa9c"),
type: new ObjectId("62076ce385b4eea8c5aeb8ba"),
title: 'qwasdasd',
content: '',
created_at: 2022-02-25T22:14:16.515Z,
updated_at: 2022-02-25T22:14:16.515Z
}
]
}
And i know that i can reach it filtering the ObjectId from user with '-_id notes.$._id' instead of { 'notes.$._id': true } and then destructuring the main object with a const { notes } resulting in this code:
const { notes } = await collection.findOne({ _id: '62141a799b646c7926fcfa9c', notes: { _id: '621954b8f073154099b92fca' } }, '-_id notes.$._id' );
But, it's the best approach to do this? Could i do it in different way being able to take advantage of findOne options like, skip, etc...?
PD: If there's some error it's because it's not the original code, i have modified it because in original code there're many abstractions.
Thanks in advance.

Can I edit multiple documents from an array of them in Mongo?

well...
I have a collection of users, one user looks like
{ userId: "someId", fullName: "AnyName", email: "anyEmail#mail.com"}
and of course Mongo adds one _id
all fine here, but a have an express server and I receive and array of existing users with a POST.
[
{ userId: "123", fullName: "name1 EDITED", email: "anyEmail1#mail.com"},
{ userId: "124", fullName: "name2 EDITED", email: "anyEmail2#mail.com"},
{ userId: "125", fullName: "name3 EDITED", email: "anyEmail3#mail.com"},
{ userId: "126", fullName: "name4 EDITED", email: "anyEmail4#mail.com"}
]
I want edit the existing user with the news values receive in the array but I don't know if I have to iterate and update each document or if I can pass the array of users to update all of them with a single query.
similar to what "insertMany" method does

MongoDB: Best way query users by given names and username

I'm trying to implement a user search that looks into the user's given names and their username, while also being able to sort results by relevance.
I tried creating a text index like this
db.users.createIndex({
username: 'text',
firstName: 'text',
lastName: 'text'
},
{
name: 'text_search',
default_language: 'en',
language_override: 'language'
})
But this doesn't take into account partial terms, so if I search for "Juan F", I get the following results
{ score: 3.7, username: "juanjo", firstName: "Juan", lastName: "Rivas F" },
{ score: 2.95, username: "Juan.rodriguez", firstName: "Juan", lastName: "Rodriguez" },
{...} // 6 more
{ score: 2.2, lastName: "Fuentes", firstName: "Juan", username: "juanfuentes" }
I understand that text indexes take into account similar words, but not partial terms, so with "Juan Fuente" I get the desired result, with "Juan F", "Juan Fu", etc, I don't.
Is there a way to improve this, in order to be able to implement a search that returns results as the user types into a search box?
Edit This is the query I tried:
db.users.find(
{ $text: { $search: "juan f" } },
{ score: { $meta: "textScore" } }
).sort({ score: { $meta: "textScore" } })

MongoDB Document Validation in Meteor?

How would one approach doing this (https://docs.mongodb.com/v3.2/core/document-validation/):
db.createCollection( "contacts",
{ validator: { $or:
[
{ phone: { $type: "string" } },
{ email: { $regex: /#mongodb\.com$/ } },
{ status: { $in: [ "Unknown", "Incomplete" ] } }
]
}
} )
In this:
// database.js
import { Mongo } from 'meteor/mongo';
export const Test = new Mongo.Collection('Test');
Thanks
you first need to define your schema in meteor.
Lists.schema = new SimpleSchema({
name: {type: String},
incompleteCount: {type: Number, defaultValue: 0},
userId: {type: String, regEx: SimpleSchema.RegEx.Id, optional: true}
});
This example defines a schema with a few simple rules:
We specify that the name field of a list is required and must be a
string.
We specify the incompleteCount is a number, which on insertion is
set to 0 if not otherwise specified.
We specify that the userId, which is optional, must be a string that
looks like the ID of a user document.
It’s pretty straightforward to validate a document with a schema. We can write:
const list = {
name: 'My list',
incompleteCount: 3
};
Lists.schema.validate(list);
In this case, as the list is valid according to the schema, the validate() line will run without problems. If however, we wrote:
const list = {
name: 'My list',
incompleteCount: 3,
madeUpField: 'this should not be here'
};
Lists.schema.validate(list);
Then the validate() call will throw a ValidationError which contains details about what is wrong with the list document.

Meteor publication: Hiding certain fields in an array document field?

I have a collection with documents like this:
{
_id: af3F3afafaa,
firstName: "John",
family: [{name: "David", relation: "brother", alive: true},
{name: "Susan", relation: "mother", alive: false}]
}
Is there a way to write a publication that hides a field in the family field array? So if I subscribed to the publication I would get:
{
_id: af3F3afafaa,
firstName: "John",
family: [{name: "David", alive: true},
{name: "Susan", alive: false"}]
}
According to the Meteor docs, something like this could work:
Meteor.publish('family', function(famId) {
return Families.find(famId, {
fields : {
"family.relation" : 0 //Exclude family.relation from the sent data
}
});
});