MongoDB / Mongoose: MarkModified a nested object - javascript

Unfortunately I don't have a record I can test this on, but I can't find any information on this anywhere.
Say I have a document like this:
{
email: {
type: 'Gmail',
data: {//freeform data},
}
}
I want to update doc.email.data. I need to use markModified() or else the data won't save correctly.
Do I mark modified like this?
doc.email.data = newData;
doc.markModified('email.data');
doc.save();
Or do I just do markModified('email') and Mongoose will work out the rest?

You need to provide the full path the modified object field, so it should be:
doc.markModified('email.data');

Related

How to add same data object to a document (MongoDB)

I am trying to uniquely store data for each server in a database, I want to be able to store multiple of the same data object. I am only able to store one because if I attempt to store another one it just replaces it, which is the issue here.
Schema
const schema = new mongoose.Schema({
reactionRole: {
type: Object,
required: false,
}
});
Screenshot of the Data
Trying to Accomplish
I want to be able to store the same object here but with different data obviously, would I have to make the schema take a Array and just insert it? I am not really sure how to work around this, thanks!
Example
This is how I want the data to be, the option to be able to add more onto the document instead of replacing it. Should I use an array or what's a solution?
reactionRole: {
<Role.name> config 1: {
Enabled: true,
Added_By: id,
MessageID: msg.id,
Emoji: <emoji>,
Role: id,
},
<Role.name> config 2: {
Enabled: true,
Added_By: id,
MessageID: msg.id,
Emoji: <emoji>,
Role: id,
}
}
I resolved this. I changed the schema to an array and sent the data as objects.

insert id into type array mongodb

My mongodb collection login is structured as so:
email: "John.doe#gmail.com"
password: "password"
full_name: "John Doe"
list_of_docs_bought: Array
0: "g81h8"
1: "fursr"
now, in my code, what I want to do is insert a new id into the list_of_docs_bought array. My code is as follows:
let collection = database.collection('login')
let doc = collection.updateOne({ email: req.session.username }, {$set: { list_of_docs_bought: '2xx729' }})
however, this isn't going to work because I need to essentially insert a new id into there, not update it. But if I use .insert(), I am not sure if that is going to work because it will insert a totally new record instead of just into the array. Can anyone offer some help?
You can use upsert which does exactly what you need.
Explanation below is taken from the official docs.
Creates a new document if no documents match the filter. For more details see upsert behavior.
Updates a single document that matches the filter.
So you would need to change your code to that:
let doc = collection.updateOne({ email: req.session.username }, {$push: { list_of_docs_bought: '2xx729' }}, { upsert: true })
Edit: You need to use the $push operator in order to add an element in an array. The $set operator will just overwrite it.

TypeORM findby Child Properties of a MongoDB Document

I have a MongoDB document in the following format. I can verify that it exists in MongoDB using Compass. I'm using TypeORM to make the query, not MondoDB.
{
_id: 'some id'
user: {
details: {
email: "test#test.ch",
username: "testname"
},
status: 'active'
}
}
Is it possible to use TypeORM to find by, say, the email?
I've tried
const emailExists = await this.userRepo.findOneBy({
user: {
details: {
email: "test#test.ch"
}
}
});
but emailExists always returns null even though I can validate that it exists in MongoDB. I've tried other ways to find by email using find, findOne, and more.
How do you find a matching value of a child property, like email? Is there a better approach?
MongoDB: Query on Nested Field
To specify a query condition on fields in an embedded/nested document, use dot notation.
Example: 'field.nestedField'
When querying using dot notation:
The field and nested field must be inside quotation marks.
Applying in your code:
const emailExists = await this.userRepo.findOneBy({'user.details.email': 'test#test.ch'});
Reference:
MongoDB Official Documentation: Query on Embedded/Nested Documents
Update: Looks TypeORM not work well with MongoDB, but you can try use $match.
Example:
$match : { 'field.nestedField': nestedField }
Applying in your code:
this.userRepo.findOneBy({$match: { 'user.details.email': 'test#test.ch' }});
If not work maybe try to change TypeORM to Mongoose.
Reference:
https://github.com/typeorm/typeorm/issues/2483

Contentful JS: Unable to retrieve entries by matching Reference field

I am using Contentful's Javascript API to build a project. Currently, I'm having an issue where I get "undefined" as a return for the following call.
const query = {
content_type: "vehicle",
include: 2,
select: "fields",
"fields.site.fields.siteName[match]": id
};
I've set up "vehicle" as a model which uses a "site" reference with names, addresses and so forth. It seems to be possible to use [exist] on the first level, like
"fields.site[exists]": true
which works, but is unsatisfactory for what I need.
What I need are any Vehicles that belong to a named Site. Obviously, I've made sure to add the relevant content, and I can indeed see the data when omitting the "fields.site.fields..." line. For security purposes, I would very much not have vehicles for other sites showing up in the response.
Am I missing something? Upping the "include" level does not do anything either.
👋🏻
I believed you didn't see one sentence in the docs.
Second is fields.brand.sys.contentType.sys.id=sFzTZbSuM8coEwygeUYes which you use to to filter on fields of entries from content type 2PqfXUJwE8qSYKuM0U6w8M.
So basically to make your query work you have also to define the content type of the entry your search query is matching against.
I quickly prototyped your case in Node.js.
const { createClient } = require('contentful');
const client = createClient({
space: '...',
accessToken: '...'
});
client.getEntries({
content_type: 'vehicle',
select: 'fields',
// this is the line you're missing
'fields.site.sys.contentType.sys.id': 'site',
'fields.site.fields.siteName': 'vw-site'
}).then(({items}) => {
console.log(items);
}).catch(e => console.log(e));
You can find a detailed example in the docs
Hope that helps :)

Mongoose: Adding an element to array

I'm using Drywall to create a website.
I'm trying to add a dashboard element to the accounts section of the admin site. The dashboard element is to store an array of dashboards (strings) that the user has access to.
I've managed to successfully add the "dashboards" into the schema and store data in it.
Here's the problem:
I need to be able to add elements to the array. The way the code stands currently replaces the contents of dashboards in the database.
I know I can use $addToSet, but I'm not sure how I'd do that since the fieldsToSet variable is sent to the findByIdAndUpdate() method as a single object.
Here's the snippet of my code:
workflow.on('patchAccount', function() {
var fieldsToSet = {
name: {
first: req.body.first,
middle: req.body.middle,
last: req.body.last,
full: req.body.first +' '+ req.body.last
},
company: req.body.company,
phone: req.body.phone,
zip: req.body.zip,
search: [
req.body.dashboards,
req.body.first,
req.body.middle,
req.body.last,
req.body.company,
req.body.phone,
req.body.zip,
]
};
req.app.db.models.Account.findByIdAndUpdate(req.params.id, fieldsToSet, function(err, account) {
if (err) {
return workflow.emit('exception', err);
}
workflow.outcome.account = account;
return workflow.emit('response');
});
});
Here's a link to the original file: (lines 184-203)
Thanks!
fieldsToSet is a bad name (at least misleading in this case), the parameter is actually update which can take $actions like $addToSet
I don't think you want to set (only) the search field with dashboards. I'm guessing that field is used to index users for a search. So you'll probably wind up doing something like this:
fieldsToSet = {
....all the regular stuff,
$addToSet: {dashboard: req.body.dashboardToAdd}
//I'm not sure that you can add multiple values at once
}
Since this is setting all of the values each time I'm not sure you actually will want to add single dashboard items. Instead you might want to get the full set of dashboards the user has and set the whole array again anyway (what if they removed one?)
fieldsToSet = {
....all the regular stuff,
dashboards: req.body.dashboards
//In this case you'd want to make sure dashboards is an appropriate array
}

Categories

Resources