I am currently working on an inventory management software in Node js and MongoDB. I am pretty new to MongoDB, having worked in Oracle and MySQL for most of my projects.
Is it possible to create a separate database schema for every client who uses my software, with each client having access only to his copy of the database schema and collections?
The equivalent of selecting data in Oracle database would be
Select * from User1.table,
Select * from User2.table etc
Also, if it were possible, how would it be implemented using a node js mongo db client like mongoose?
I looked at MongoDB documentation, but it talks mainly about adding users to a database for authorization.
I apologize if it seems like a silly question, but id appreciate it if someone could point me in the right direction for this.
Before starting to invest a lot of time in the development of your project, check out other possible approaches to the scenario that you are trying to build.
I did a quick search on SO and found some additional threads with similar scenarios:
MongoDB Database vs. Collection
MongoDB Web App - Database per User
Additional info about mongoose database creation
Whenever you call the connect method on the mongoose object, you are either connecting to an existing database or you are creating it in case it doesn't already exist.
You could have a function that allows you to pass in a name argument with the name and create databases programmatically:
function createDatabase(name) {
var conn_string = 'mongodb://localhost/';
if (typeof name == 'string') {
conn_string += name;
}else{
return false;
}
mongoose.connect(conn_string);
}
Also, be aware that a database will be created when you first insert a record in a collection of that particular database.
It is not sufficient to only connect to the database, you also have to insert a record.
As per my previous example, you could also pass a schema parameter to the function, tailored to each user's profile and fire an insert statement after you connect to that database.
Related
When connecting to MongoDB with a Node.JS application using express, how do you connect to just one collection if the database has multiple collections?
I have the following MONGODB_URI:
MONGODB_URI=mongodb+srv://username:******#cluster0.dayw5.mongodb.net/phonebook?retryWrites=true&w=majority
The database "phonebook" has three collections, "numbers", "users" and "people". How do you change the MONGODB_URI to just connect to "numbers" ?
At the moment, the connection is successful, but nothing is being fetched.
You don't; the connection URI is granular to the database only, in your case phonebook. From the resources returned, you must specify a collection to access e.g. coll = db['users'] and then perform operations against that collection object e.g.
c = coll.find({name:"foo"});
c.forEach(function(doc) {
printjson(doc);
});
Both answers given above are basically correct.
I tried to connect to an existing collection but was unable to do so. Instead, MongoDB automatically creates a new collection in the database and gives it a new, custom name: "people" in my case which I did not specify anywhere.
I'm currently using mongodb in a express application via mongoose and a random thought came upon me. What would happen if say you had a site with users and later on you made a update and needed to add a new field to all the user models. how would you go about updating all pre-existing users with the new field.
You would use updateMany in your mongo shell (or using driver - the same):
db.user.updateMany({}, { $set: { newField: value } });
I'm developing a Xamarin.Forms app which uses an Azure app service with SQL database linked through EasyTables. I've run the samples and successfully tested querying tables etc on the server and enabled offline sync so as a localdb is created.
I've created the store, defined the table & sync'd it, however I want to be able to query it somehow with a where clause - is that possible? Can I add a where clause to the client.GetSyncTable line?
var store = new MobileServiceSQLiteStore("localstore.db");
store.DefineTable<Journey_Stages>();
client.SyncContext.InitializeAsync(store);
tbl_Stages = client.GetSyncTable<Journey_Stages>();
Some of the tables I'm pulling down will grow over time & are linked to individual user profiles, so I only want data which belongs to that user and I don't want to be bringing down masses of data each time, preferably let the server handle that and only bring down what I need on a user by user basis.
Thanks,
Steve
You should add this filtering logic on the server side, so that each user's data isn't exposed to all your other users. See for example this sample if you are using the Node.js backend -- line 17 adds a WHERE clause for the table read query. If you have the .Net backend, similar logic would go in your table controller.
// Configure specific code when the client does a request
// READ - only return records belonging to the authenticated user
table.read(function (context) {
context.query.where({ userId: context.user.id });
return context.execute();
});
I am using pg-promise on Node 7.2.1 with PostgreSQL 9.4. I am using the code below to connect to the PostgreSQL server:
// pg-promise connection elements.
// Database initialization options.
const pg_options = {
// Initialization options.
};
// Create an instance of the pg-promise library.
const g_pg_promise = require('pg-promise')(pg_options);
// Connection string for a local connection to the 'summarize' database.
const g_pg_connection =
{
host: 'localhost',
port: 5432,
database: 'db_stats',
user: 'db_user',
password: '{password here}'
}
// Connect to the database.
const g_pg_database = g_pg_promise(g_pg_connection);
// Expose the database object globally. The database object should only
// be instantiated once and then shared.
module.exports = {
g_pg_promise: g_pg_promise,
g_pg_database: g_pg_database
};
I know the connection parameters are valid because I use the exact same values in other non-Node.JS apps to connect to the same PostgreSQL server. I also know that db_stats is a valid database name. I have worked with that database for quite a while with other non Node.JS apps and via pgAdmin 3.x.
However, when I attempt to connect using pg-promise I get the following error:
error: relation "db_stats" does not exist
I did see the SO post below:
Unable to query PostgreSQL database in NodeJS using pg-promise - "relation does not exist"
But that post did not make sense to me because I believe Vitaly, the author of pg-promise, was telling the poster that he did not have a table called users, when it looks to me that the poster was trying to access the database called users and he definitely had a database with that name.
In any case, I definitely have a database named db_stats so I'm not sure why I am getting this error. How can I solve this?
error: relation "db_stats" does not exist
The error you get from PostgreSQL is not referring to a database named "db_stats", but to a relation (either a table or a view) with that name.
That is, db_stats most probably appears in the FROM clause of a SELECT query (although it may be also a INSERT, UPDATE, DELETE, ...).
There is neither a db_stats table nor a view in your database. Or, maybe, it exists, but it exists in a schema that is not part of your current search_path.
To find out, check two things:
SELECT
*
FROM
information_schema.tables
WHERE
table_name = 'db_stats' ;
If there is a table there... you already know which schema(s) contains it/them.
Then, make sure that this schema is part of your search_path by means of:
SHOW search_path ;
You might have to execute this SQL statements by adding the adequate code to your application, and use a debugger to check what's returned in that environment.
Can anyone guide me on how to setup relational schema & performs joins in sails.js?
Associations are officially Supported in Waterline
Overview
From the docs:
With Sails and Waterline, you can associate models across multiple data stores. This means that even if your users live in PostgreSQL and their photos live in MongoDB, you can interact with the data as if they lived together in the same database. You can also have associations that span different connections (i.e. datastores/databases) using the same adapter. This comes in handy if, for example, your app needs to access/update legacy recipe data stored in a MySQL database in your company's data center, but also store/retrieve ingredient data from a brand new MySQL database in the cloud.
Supported Association Types
One to Many
Many to Many
Cross-adapter Dominance
One to One
One Way
Planned Association Types
Through Associations
Original Post
I'm the author of Waterline, the ORM used in Sails. Waterline is brand
new and we are adding features all the time. Currently we don't have
support for associations but it's next on the roadmap. We worked out
an API for associations that I think most people will really like. You
can view the work in progress and the proposed API at: [Proposed Sails
Associations API][1].
We are going to tackle Associations and Transactions next and hope to
have them ready in the next month or so.
In the mean time if you are using the MySQL or PostgreSQL adapters
they both expose a raw .query() method that allows you to pass in a
hand built sql query and have it executed. I totally realize this
isn't ideal but should allow you to continue building your app while
we get support for associations and joins.
The function signature for the query method is:
Model.query(<sql query>, <optional data>, callback);
The example from particle banana works but should actually use "new" like "var instance = new User._model(values)". I'm using the following code and it works.
Accounts.query(query, function(err, accounts) {
if (err)
return fn(err);
accounts = _.map(accounts, function(account) {
return new Accounts._model(account);
});
fn(null, accounts);
});