Nedb Multiple Collection Single Datastore - javascript

I am a new to nedb. Its a kinda what sqlite is for sql community but for the node.js community.
[https://github.com/louischatriot/nedb]
I wanted to ask is possible to have multiple collections in a single database file (datastore).
If there is, could please show me some code sample on how to go about it?
I have tried this:
var Datastore = require('nedb'),
databaseURL="tudls.db",
db = new Datastore({filename: databaseURL, autoload: true});
This creates a single datastore called db.
From the documentation, I saw that nedb is mongo-like. So to insert a record I tried this:
app.post('/todos', function(req, res){
var task = req.body.text;
db.todols.insert({text: task, done: false}, function(err, saved){
if(err||!saved){
res.send("Task not saved...");
}
res.send("Task saved...");});
});
However, I get a 'cannot call method insert of undefined.' I thought that if I call the collection name (todols) when inserting a record it would work so that I can proceed to add another collection to the datastore (db.user) but I was mistaken.
Hence, is it possible to have multiple collections in a single datastore or am I to have a datastore for each collection? If it is possible, does anyone know how to achieve this?
Thank you...

This really is a "lite" interpretation of MongoDB and as such there really isn't the same concept of "databases" and "collections" that exists in the full featured product, as well as omitting a lots of other features.
If you want things to appear as if you do have various "collections", then as suggested in the manual page you define various DataStore objects within a structure to make things look that way:
var db = {};
db.todols = new DataStore('/path/to/todols.db');
db.other = new DataStore('/path/to/other.db');
That makes it appear that you have "collections" which are in fact to "neDB" actually just DataStore objects.

//create multiple collections
var Datastore = require('nedb');
var db = {};
db.users = new Datastore('path/to/users.db');
db.robots = new Datastore('path/to/robots.db');
//access it
db.users.loadDatabase();
db.robots.loadDatabase();
//find some documents
db.users.find({name: "john"}, function (err,docs){ console.log(docs); });

Related

Specify different unique key in Dexie database schema?

My basic dexie database scheme is something like this.
const db = new Dexie('MyDatabase');
// Declare tables, IDs and indexes
db.version(1).stores({
myrecords: 'record_id'
});
I want to use my record_id as a unique key. In indexeddb I can do this like the below
var myrecordsObjectStore = db.createObjectStore('myrecords' , {
keyPath: 'record_id'
});
Should work using & prefix for unique as noted in docs
db.version(1).stores({
myrecords: '&record_id'
});
See Dexie Quick Reference

Update Array from Document (MongoDB) in Javascript not Working

I've looking for an answer for like 5 five hours straight, hope somebody can help. I have a MongoDb collection results (I'm using mLab) which looks like this:
{
"user":"5818be9c74aaec1824c28626"
"results":[{
"game_id":14578,
"level1":-1,
"level2":-1,
"level3":-1
},
{ ....
}],
{ "user":....
}
}
"user" is a MongoID I save in a previous part of the code, "results" is a record of scores. When an user does a new score, I have to update the score of the corresponding level (I'm using NodeJS).
This is one of the things I've tried so far.
app.get('/levelCompleted/:id/:time', function (request, response) {
var id = request.params.id;
var time = parseInt(request.params.time);
var u= game.getUserById(id);
var k = "results.$.level"+(u.level);
//I build the key to update dinamycally
dbM.collection("results").update(
{user:id,
"results.game_id":u.game_id
//u has its own game_id
},
{$set: {k:time}}
);
...
response.send(...);
});
I've checked the content of every variable and parameter, tried also using $elemMatch and dot notation, set upsert and multi, with no results. I've used an identical command on mongo shell and it has work on the first try.
Update with Mongo Shell
If someone could tell me what I'm doing wrong or point me in the right direction, it would be great.
Thanks
When you use a MongoId as a field in a MongoDB, you can't just pass a string with the id to do the query, you have to identify that string as an ObjectId (Id type in Mongo). Just add a new require in your node.js file.
var ObjectID = require("mongodb").ObjectID;
And use the imported constructor in your update request.
dbM.collection("results").update(
{user:ObjectID(id),...
...
}

Querying a parse table and eagerly fetching Relations for matching

Currently, I have a table named Appointments- on appointments, I have a Relation of Clients.
In searching the parse documentation, I haven't found a ton of help on how to eagerly fetch all of the child collection of Clients when retrieving the Appointments. I have attempted a standard query, which looked like this:
var Appointment = Parse.Object.extend("Appointment");
var query = new Parse.Query(Appointment);
query.equalTo("User",Parse.User.current());
query.include('Rate'); // a pointer object
query.find().then(function(appointments){
let appointmentItems =[];
for(var i=0; i < appointments.length;i++){
var appt = appointments[i];
var clientRelation = appt.relation('Client');
clientRelation.query().find().then(function(clients){
appointmentItems.push(
{
objectId: appt.id,
startDate : appt.get("Start"),
endDate: appt.get("End"),
clients: clients, //should be a Parse object collection
rate : appt.get("Rate"),
type: appt.get("Type"),
notes : appt.get("Notes"),
scheduledDate: appt.get("ScheduledDate"),
confirmed:appt.get("Confirmed"),
parseAppointment:appt
}
);//add to appointmentitems
}); //query.find
}
});
This does not return a correct Clients collection-
I then switched over to attempt to do this in cloud code- as I was assuming the issue was on my side for whatever reason, I thought I'd create a function that did the same thing, only on their server to reduce the amount of network calls.
Here is what that function was defined as:
Parse.Cloud.define("GetAllAppointmentsWithClients",function(request,response){
var Appointment = Parse.Object.extend("Appointment");
var query = new Parse.Query(Appointment);
query.equalTo("User", request.user);
query.include('Rate');
query.find().then(function(appointments){
//for each appointment, get all client items
var apptItems = appointments.map(function(appointment){
var ClientRelation = appointment.get("Clients");
console.log(ClientRelation);
return {
objectId: appointment.id,
startDate : appointment.get("Start"),
endDate: appointment.get("End"),
clients: ClientRelation.query().find(),
rate : appointment.get("Rate"),
type: appointment.get("Type"),
notes : appointment.get("Notes"),
scheduledDate: appointment.get("ScheduledDate"),
confirmed:appointment.get("Confirmed"),
parseAppointment:appointment
};
});
console.log('apptItems Count is ' + apptItems.length);
response.success(apptItems);
})
});
and the resulting "Clients" returned look nothing like the actual object class:
clients: {_rejected: false, _rejectedCallbacks: [], _resolved: false, _resolvedCallbacks: []}
When I browse the data, I see the related objects just fine. The fact that Parse cannot eagerly fetch relational queries within the same call seems a bit odd coming from other data providers, but at this point I'd take the overhead of additional calls if the data was retrieved properly.
Any help would be beneficial, thank you.
Well, in your Cloud code example - ClientRelation.query().find() will return a Parse.Promise. So the output clients: {_rejected: false, _rejectedCallbacks: [], _resolved: false, _resolvedCallbacks: []} makes sense - that's what a promise looks like in console. The ClientRelation.query().find() will be an async call so your response.success(apptItems) is going to be happen before you're done anyway.
Your first example as far as I can see looks good though. What do you see as your clients response if you just output it like the following? Are you sure you're getting an array of Parse.Objects? Are you getting an empty []? (Meaning, do the objects with client relations you're querying actually have clients added?)
clientRelation.query().find().then(function(clients){
console.log(clients); // Check what you're actually getting here.
});
Also, one more helpful thing. Are you going to have more than 100 clients in any given appointment object? Parse.Relation is really meant for very large related collection of other objects. If you know that your appointments aren't going to have more than 100 (rule of thumb) related objects - a much easier way of doing this is to store your client objects in an Array within your Appointment objects.
With a Parse.Relation, you can't get around having to make that second query to get that related collection (client or cloud). But with a datatype Array you could do the following.
var query = new Parse.Query(Appointment);
query.equalTo("User", request.user);
query.include('Rate');
query.include('Clients'); // Assumes Client column is now an Array of Client Parse.Objects
query.find().then(function(appointments){
// You'll find Client Parse.Objects already nested and provided for you in the appointments.
console.log(appointments[0].get('Clients'));
});
I ended up solving this using "Promises in Series"
the final code looked something like this:
var Appointment = Parse.Object.extend("Appointment");
var query = new Parse.Query(Appointment);
query.equalTo("User",Parse.User.current());
query.include('Rate');
var appointmentItems = [];
query.find().then(function(appointments){
var promise = Parse.Promise.as();
_.each(appointments,function(appointment){
promise = promise.then(function(){
var clientRelation = appointment.relation('Clients');
return clientRelation.query().find().then(function(clients){
appointmentItems.push(
{
//...object details
}
);
})
});
});
return promise;
}).then(function(result){
// return/use appointmentItems with the sub-collection of clients that were fetched within the subquery.
});
You can apparently do this in parallel, but that was really not needed for me, as the query I'm using seems to return instantaniously. I got rid of the cloud code- as it didnt seem to provide any performance boost. I will say, the fact that you cannot debug cloud code seems truly limiting and I wasted a bit of time waiting for console.log statements to show themselves on the log of the cloud code panel- overall the Parse.Promise object was the key to getting this to work properly.

fetching data from other collections inside Mongoose find method

I'm working on a App with Node.js and mongoose(mongodb). Is there any way to fetch information from other collections inside find method except model population? population works with _id and my id's in the other collection cant be duplicate and i cant have one to many relation.
For example every user has more than one books. in the books schema _id's should be duplicate and a bunch of them has the same user id. But i don't want this. i want to compare other field.
I read document#population in Mongoose documentation but i can't understand:
http://mongoosejs.com/docs/api.html#document_Document-populate
i can't believe for this simple need, Mongoose doesn't have a good api.
this is my schema's:
var mongoose = require('mongoose');
var Users = require('../users');
var schema = new mongoose.Schema({
book_name: String,
book_publisher: String
});
var book = mongoose.model('book', schema);
module.exports = book;
And
var mongoose = require('mongoose');
var Book = require('../book');
var Schema = mongoose.Schema;
var schema = new mongoose.Schema({
user_name: String,
books: [{ type: Schema.Types.ObjectId, ref: 'Book' }]
});
var users = mongoose.model('users', schema);
module.exports = users;
Essentially, the problem is not with mongoose but mongo. What you're trying to do is basically pull relational data in a non-relational database. From experience I suggest not doing this. If you can't avoid it, use postgres. Postgres supports json data.
In mongoose you can load first level relations (users -> posts) using the .populate method. If you want to pull in a second level relation (users -> posts -> replies), then you end up needing to manually create joins in code.
So if a user has multiple books, you can setup your schemas like this.
User = new mongoose.Schema({
//existing user properties
owned_books: [{type: mongoose.Schema.Types.ObjectId, ref: 'book'}]
}}
//now you can query users and populate their books by doing
Users.find().populate('owned_books').exec(callback)
Edit: It could go the other way around, where the book has a collection of users. In any case, _id needs to be unique in a table, but as a field of another document it does not need to be unique, unless you've put an index on that field.

Chaining models relations in node.js (node-orm) like in Rails

I'm building a relatively big NodeJS application, and I'm currently trying to figure out how to fetch the data I need from the DB. Here is a part of my models :
One user has one role, which has access to many modules (where there's a table role_modules to link roles and modules).
In Rails, I would do something like user.role.modules to retrieve the list of the modules he has access to. In NodeJS it's a bit more complicated. I'm using node-orm2 along with PostgreSQL. Here is what I have so far:
req.models.user.find({email: req.body.user}, function(err, user) {
user[0].getRole(function(err, role) {
role.getModules(function(err, modules) {
var list_modules = Array();
modules.forEach(function(item) {
console.log(item);
list_modules.push(item.name);
})
But I can't do this, because item only contains role_id and module_id. If I want to have the name, I would have to do item.getModule(function() {...}), but the results would be asynchronous ... so I don't really see how I could end up with an array containing the names of the modules a user has access to ... have any idea?
Also, isn't that much slower than actually running a single SQL query with many JOIN? Because as I see it, the ORM makes multiple queries to get the data I want here...
Thank you!
I wrote an ORM called bookshelf.js that aims to simplify associations and eager loading relations between models in SQL. This is what your query would probably look like to load the role & modules on a user given your description:
var Module = Bookshelf.Model.extend({
tableName: 'modules'
});
var Role = Bookshelf.Model.extend({
tableName: 'roles',
modules: function() {
return this.belongsToMany(Module);
}
});
var User = Bookshelf.Model.extend({
tableName: 'users'
role: function() {
return this.hasOne(Role);
}
});
User.forge({email: req.body.user})
.fetch({
require: true,
withRelated: ['role.modules']
})
.then(function(user) {
// user, now has the role and associated modules eager loaded
console.log(user.related('role'));
console.log(user.related('role').related('modules'))
}, function(err) {
// gets here if no user was found.
});
Might be worth taking a look at.

Categories

Resources