Write an object containing an array of objects to a mongo database in Meteor - javascript

In my user collection, I have an object that contains an array of contacts.
The object definition is below.
How can this entire object, with the full array of contacts, be written to the user database in Meteor from the server, ideally in a single command?
I have spent considerable time reading the mongo docs and meteor docs, but can't get this to work.
I have also tried a large number of different commands and approaches using both the whole object and iterating through the component parts to try to achieve this, unsuccessfully. Here is an (unsuccessful) example that attempts to write the entire contacts object using $set:
Meteor.users.update({ _id: this.userId }, {$set: { 'Contacts': contacts}});
Thank you.
Object definition (this is a field within the user collection):
"Contacts" : {
"contactInfo" : [
{
"phoneMobile" : "1234567890",
"lastName" : "Johnny"
"firstName" : "Appleseed"
}
]
}

This update should absolutely work. What I suspect is happening is that you're not publishing the Contacts data back to the client because Meteor doesn't publish every key in the current user document automatically. So your update is working and saving data to mongo but you're not seeing it back on the client. You can check this by doing meteor mongo on the command line then inspecting the user document in question.
Try:
server:
Meteor.publish('me',function(){
if (this.userId) return Meteor.users.find(this.userId, { fields: { profile: 1, Contacts: 1 }});
this.ready();
});
client:
Meteor.subscribe('me');

The command above is correct. The issue is schema verification. Simple Schema was defeating the ability to write to the database while running 'in the background'. It doesn't produce an error, it just fails to produce the expected outcome.

Related

Query stored values that contain specific string

I have a small realtime firebase database that's set up like this:
database
-messages
--XXXXXXXXXXXX
---id : "XXX-XXX"
---content : "Hello world!"
It's a very simple message system, the id field is basically a combination of users id from my mysql database. I'm trying to return all messages that match one of the ids, either sender or receiver. But I can't do it, seems like firebase only support exacts querys. Could you give me some guidanse?
Here's the code I'm working with
firebase.database().ref("messages").orderByChild("id").equalTo(userId).on("value", function(snapshot)
I'm looking for something like ".contains(userId)"
Firebase supports exact matches (with equalTo) and so-called prefix queries where the value starts with a certain value (by combining startAt and endAt). It does not support querying for values that end with a certain value.
I recommend keeping a mapping from each user IDs to their messages nodes, somewhere separately in their database.
So say that you have:
messages: {
"XXXXXXXXXXXX": {
id : "YYY-ZZZ",
content : "Hello world!"
}
}
You also have the following mappings:
userMessages: {
"YYY": {
"XXXXXXXXXXXX": true
},
"ZZZ": {
"XXXXXXXXXXXX": true
}
}
Now with this information you can look up the messages for each user based on their ID.
For more on the modeling of this type of data, I recommend:
Best way to manage Chat channels in Firebase
Many to Many relationship in Firebase
this artcle on NoSQL data modeling

Auth0: How to add custom properties to UserObject?

Hello dear StackOverFlow community,
i don't know much about Auth0 and need help. And I wonder how to add my own properties when creating a user? just for info i have connected Auth0 to my own MongoDB atlas database.
i want to add a customId when creating a user, and this should be a 16-digit random number.
And my userObj should then look something like this:
{
_id: ObjectId("5f720126054c87001662a138"),
connection:"MongoDB"
client_id:"zoClZ3gZE56iwblHXQ1vgwEcLfYr81Bx"
email:"gustek#gustek.com"
username:"gustek"
password:"$2b$10$dE69gGsDqVfWtmnXZ6EaKetILUmEju8N9PVjtDpgzzAp4jYNQbe8G"
tenant:"dev-test"
email_verified:false
customId:"9829539769841530"
}
I mean I found something in the documentation but I do not know how to implement it:
https://auth0.com/docs/users/set-metadata-properties-on-creation
Do I have to do it over this surface?
As I said before, I have no idea how I could achieve this. I am grateful for every answer!
You can use an app_metadata property in the user object to store data that is not part of the normalized user profile. This would include a custom UUID like you described here.
The user object would look like this:
{
client_id: "<ID of creating client (application)>",
tenant: "<name of creating Auth0 tenant>",
email: "<email address for the user>",
password: "<password for the user>",
username: "<name associated with the user>",
user_metadata: {
"language": "en"
},
app_metadata: {
"custom_id": "1234567890"
}
}
While user_metadata and app_metadata are optional, if supplied, they do not need to be stored in the legacy identity store; Auth0 automatically stores these values as part of the user profile record created internally. These values are (optionally) provided as a reference: their contents potentially being influential to legacy identity creation.

Firebase database: how to get first record of each list

I have a nested firebase database with a structure like this:
posts: {
0: {
title: "...",
content: '...',
comments: [{
by: "someone"
}, {
by: "anotherone"
}]
},
1: {
...
}
}
Now I want to get the first comments on each post so I tried
firebase.database().ref('/posts/{postId}/comments/0').once('value',function(snapshot){
snapshot.forEach(function(child){ console.log(child.val());});
})
But don't know why the only thing I got in the console is false. So are there anyone knows what's wrong or is it impossible to query like that?
The Firebase Database SDKs will also read entire nodes. It is not possible to retrieve a subset of a node's data or to get just the keys.
To get the first comment of each post, you must know the key of each post already. Since you can't read just the keys of the posts, this means that you must read all data to get just the first comment of each post:
firebase.database().ref('/posts').once('value',function(snapshot){
snapshot.forEach(function(child){
console.log(child.val().comments[0]);
});
})
While this gives the result you need, it is quite wasteful in bandwidth: the client is ready way more data than you need. As usual in NoSQL databases, a better solution may require you to change your data model to fit your use-case. For example: consider storing the latest comment for each post in a separate top-level list:
latest-comments: {
0: {
by: "someone"
},
1: {
...
}
}
You will need to update this list (in addition to your original comments list) whenever a new comment is posted. But in return, reading the latest comment for each post is now very cheap.

when I try to use find inside loopback model js file.iam getting error as Error: Cannot call user.find(). The find method has not been setup

Error: Cannot call user.find(). The find method has not been setup. The PersistedModel has not been correctly attached to a DataSource!
user.js is inside server/models/user.js
module.exports = function(User) {
User.find({where: {id:'3'}}, function(err,data) {
console.log(err);
console.log(data);
});
};
Your current model-config.json file has this line:
"user": { "dataSource": "db" }
Make the U capital in user as this is creating a new model user with lowercase letter and i think you haven't created its model files like user.js and user.json. It looks like you want to extend the built-in User model, in that case you can use this lowercase user model but keep both the model definitions in the model-config.js and use User as base in user.json file. Check Docs there is clear explanation for this
This is nothing to do with the "user" having a lowercase "u". Following the StrongLoop documentation, it looks like you've generated a model but not linked it to a data source.
In the documentation, it advises you to create a model and then change the datasource afterward. When you generate your model, the storage that is available for you to set will only be "db", which is an in-memory provider.
To get your API path to work correctly, firstly generate your model using:
slc loopback:model
Once you have generated your model, then run:
slc loopback:datasource
Which will then prompt you to fill in some options about your data source. Here's an example using MongoDB (note, where there is no data after the ':' is where you press enter to use the default value):
? Enter the data-source name: name_i_want_to_use_for_this
? Select the connector for name_i_want_to_use_for_this: MongoDB (supported by StrongLoop)
Connector-specific configuration:
? Connection String url to override other settings (eg: mongodb://username:password#hostname:port/database):
? host: localhost
? port:
? user:
? password:
? database: mydbname
? Install loopback-connector-mongodb#^1.4 Yes
This will then provide you with a connection provider called name_i_want_to_use_for_this. Now go into your /server/model-config.json and then scroll down to the name of your model and you will see:
"name_of_my_model": {
"dataSource": "db",
"public": true
}
Change this to:
"name_of_my_model": {
"dataSource": "name_i_want_to_use_for_this",
"public": true
}
Now you're done, go back into your strongloop project directory and run node ., and browse to http://localhost:3000/explorer. Go to the method you wanted to test, and test it in the explorer again, and it should now insert the data into the model.
To test this has worked, create a new record using the explorer, and then query its ID using the explorer.

node.js how to handle change of objects and variables in callbacks

I have just started a large project with node.js and I have stumbled upon some callback nightmare issues. I have done some node.js development before, but only small stuff based on tutorials.
I have a user model and a owner model, who is the owner for that user...basically the part I am building in node.js will be a REST service so I need to send a json containing a user and it's owner name. My problem is trying to get the owner name like I would do it in ruby or php and setting it as a property..but it doesn't work.
How do people handle this kind of logic in node.js where you need to change objects in callback functions? Also I do not want it to affect performance.
I am using mysql as the database because this was a requirement. So the code is this:
//find all
req.models.users.find({
'id' : req.query.id
}, function(err, users) {
if (err) console.log(err); //do something better here
else {
var json = [];
users.forEach(function(user) {
user.getOwner(function(err, owner) {
user.accountOwner = owner.name;
json.push(user;
});
});
res.type('application/json');
res.send(json);
}
});
I want to send something like this:
[{
'id': user.id,
'username": user.username,
'email': user.email,
'owner': user.owner.name'
},
{...}]
The problem is you are not understanding the control flow of node code. It doesn't go line by line top to bottom in chronological order. So your issue is your res.send(json) happens BEFORE (in time) your user.getOwner callback executes, so you send your empty json, then you stuff things into the json array after it's already been sent. You need to use something like async.each to do your joins, wait for all of the user`s owners to be populated, and then send the response. Or you could actually let the database join the data by writing a SQL join instead of doing N+1 queries against your database.

Categories