So I think I am doing something stupid, because I can't for the life of me get the following schema to work properly:
UserSchema = new mongoose.Schema
notifications:
discussion:
created:
mobile:
stuff:
hey:
type: Boolean
default: false
osx:
type: Boolean
default: false
web:
type: Boolean
default: true
email:
type: Boolean
default: true
sms:
type: Boolean
default: false
All looks normal, right? Just declaring some nested properties, their types, and their defaults? Nope.
Information.db.User.find {}, "notifications userSettings", (err, users) ->
for user in users
console.log user.notifications.discussion.created
// prints { mobile: { stuff: {} } }
All defaults gone, and the actual data I want to store is no where. Any ideas???
Edited to include the code for retrieving the user. Information.db.User is a refernce to the Mongoose Schema, skipping over my caching layer. The user already exists in the db, and I am trying to add the notifications object instead of having those settings stored as stringified JSON.
I'm pretty sure you have old user objects in your database that were created before you added the defaults or maybe they were left over from another project.
When I implemented your code in my test project I used an old database which already had existing users in it and got the same output as you did. I guess mongoose tries to force the schema on these user objects but it will only output the nested fields and none of the boolean fields since they are null.
When I created a new object with your schema it worked fine and I got values for all the default. Please let me know if this might have been the issue for you too.
Related
I have a working code below that inserts a data if it does not exist (but not updates if it exist). In below implementation I am looping upsert, and it just works fine.
My question is, how to get those newly inserted data? (exclude data that is already existing). Do have idea how to achieve this, in a shortest way as possible?
I did some research about it and found this possible github solution, but I don't get the point. Because it also returning data even its already existing.
this.data = await prisma.$transaction(
temp.map((provider) =>
prisma.provider.upsert({
where: {
user_id_api_key: {
user_id: provider.user_id,
api_key: provider.api_key
}
},
create: provider,
update: {}
})
)
)
console.log(this.data) // it still return data even if its already existing
I've noticed this funny thing when instantiating the model in mongoose - the instance can be changed through other means than instance itself. Here's an example:
var articleSchema = new Schema({
name: 'String',
price: 'Number'
});
var Article = mongoose.model('Article', articleSchema);
var nexus = new Article({
name: 'Nexus 5',
price: 300
});
nexus.save(function(err, instance) {
instance.name = 'Nexus Five';
instance.save(function(err, instance2) {
instance2.name = 'Nexus 5ive';
instance2.save(function(err, instance3) {
console.log(nexus.name); //'Nexus 5ive'
});
});
});
As you can see in the example I never changed the name property of nexus, I changed the properties of the model that save function returned in the callback. Is it OK to approach changing the data in this way? Or should I just stick to the firstly defined instance (i.e. nexus variable)? It seems a bit confusing, since you can easily lose control on what you're dealing with.
The save function returns a model. If you wish you can continue modifying it.
But as the model instance you get back will always be exactly the same as the one you saved, I can't imagine when it would be truly useful not to to just keep mutating the original model. By the same token when would you ever mutate the original document, save it, mutate it again, then save it again? I'm not coming up with any scenarios where I would write the code in your example.
If you call findOneAndUpdate with the new option, suddenly the returned model instance becomes useful, since it's a fresh copy of the document (one which might have been mutated by another client).
I am new to sails js. I created a model :
module.exports = {
attribute: {
firstName:{
type: 'string',
required: true,
},
};
and the data was getting inserted even if i pass " firstName:'' ". It was happening because it should be "attributes" and not "attribute". Can anyone tell me why they both are different? Thank you.
Well, your key attribute that specifies a model's attributes was wrong so it treated the model as if there were no required attributes (or any at all). The parameter can still be passed when creating the model, but nothing would be done with it. That means that a model instance would still be created regardless of what parameters you passed or did not pass in.
See the Waterline documentation for more details about models.
I'm a couple hours new to Meteor and Mongo, coming from a Rails background and trying to understand how migrations work - or don't maybe?
I have a server/bootstrap.js file that I use to seed some data:
// if the database is empty on server start, create some sample data.
Meteor.startup(function () {
if (Users.find().count() === 0) {
var userData = [
{ name: 'Cool guy' },
{ name: 'Other dude' }
];
for (var i = 0; userData.length; i++) {
var userId = Users.insert({
name: userData[i].name
});
}
}
});
It seems like every time I want to change the database, say to add a new field, I have to run meteor reset to get it to pick up the changes.
But what happens if I create records or other data through the UI that I want to keep? In Rails, working with MySQL or PostgreSQL, I'd create a migration to create new fields without blowing away the entire database.
How does this work with Meteor and Mongo? Also thinking of the case of rolling out new changes from development to production. Thanks!
-- Update: 2013/09/24 --
Apparently, the schema-less nature of Mongo reduces or eliminates the need for migrations. In my case, modifying userData to add new fields won't work after it runs initially because of the Users count check - which is why I kept running meteor reset. I'll need to rethink my approach here and study up.
That said, there are projects out there that use migrations, like Telescope: https://github.com/SachaG/Telescope/blob/master/server/migrations.js
I also found the tutorial at http://try.mongodb.org/ useful.
First of all, your code is perfectly valid. And you know that.
mrt reset gives you a 'fresh' - empty database (as mentionned already).
If you want to reset a particular collection, you can do it so :
MyCollection.remove({});
But you have to understand the nature of NoSQL : there are no constraints on the data. It could be called NoREL (as in not a relational database, source : Wikipedia ).
MongoDB is also schema-less.
This means that you can use any field you want in your data. This is up to you (the programmer) to enforce specific constraints if you want some. In other words, there is no logic on the mongo side. It should accept any data you throw at it, just like Hubert OG demonstrated. Your code snippet could be :
// if the database is empty on server start, create some sample data.
Meteor.startup(function () {
if (Users.find().count() === 0) {
var userData = [
{ name: 'Cool guy' },
{ name: 'Other dude' },
{ nickname: 'Yet another dude' } // this line shows that mongo takes what you throw him
];
for (var i = 0; userData.length; i++) {
var userId = Users.insert({
name: userData[i].name
});
}
}
});
Source : http://www.mongodb.com/nosql
There is no need for migration there. You only have to add the logic in your application code.
Note : To import/export a database, you can have a look there : mongo import/export doc, and maybe at the db.copyDatabase(origin, destination, hostname) function.
There are no migrations in Mongo — there is no scheme! If you want to add a new field that was not there before, just do it and it will work. You can even have completely different documents in the same collection!
Items.insert({name: "keyboard", type: "input", interface: "usb"});
Items.insert({cherries: true, count: 5, unit: "buckets", taste: "awesome"});
This will just work. One of main reasons to use NoSQL (and advantages of Meteor over Rails) is that you don't have migrations to worry about.
Using mrt reset to change db model is a terrible idea. What it actually does is complete reset of db — it removes all of your data! While it's sometimes usefull in development, I bet it's not what you want in this case.
I am having some trouble making the publish function work with Meteor. The code I am using is as follows:
Meteor.publish "adminArea", () ->
Meteor.users.find({
admin: true
}, {
fields: {
permissions: 1
}
})
and I am subscribing with:
Meteor.subscribe "adminArea"
This doesn't work though, when I run Meteor.user() in the console it just returns the default options.
If I run db.users.find({"admin": "true"}) in Mongo the correct information is returned.
The annoying thing is, this used to work perfectly until I reset my database with Meteor reset. Would this be messing it up or does anyone know what I am doing wrong now?
Thanks for any help.
I have now fixed this issue and it was complete error on my part. I had forgot to add the permissions field to the user in the database so when it ran the query, it would find admin: true but then be unable to return the permissions field because it didn't exist.
So note to self: Always add the necessary fields to the user.
Oops!
Thanks