fetching data from other collections inside Mongoose find method - javascript

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.

Related

Mongoose how to see which mongodb query is being generated nothing returned from database

I'm currently using mongodb with mongoose.
When I connect to the database via the terminal and run the command:
db.locphoto.find({})
It successfully returns the list of items that I'm looking for.
Alternatively, on my application I do the following and unfortunately it constantly returns []. I was hoping someone could show me the way to see which mongodb query is generated so that I'm able to check if it is correctly generating db.locphoto.find({}).
My controller code is as follows:
var LocPhoto = require('../models/locPhoto');
module.exports.getGalleryPictures = function(req, res) {
LocPhoto.find({}, function(err, results) {
res.json(results);
});
}
And my model code is as follows:
var mongoose = require('mongoose');
var locPhotoSchema = mongoose.Schema({
challengeId: String,
image: String,
main: Number,
});
module.exports = mongoose.model('LocPhoto', locPhotoSchema);
I'd really appreciate if someone knows how to see the command that is being generated so that I can check this better in the future, since I've had this issue a few times already, it's usually to do with capital letters etc.
You're not properly creating the schema , you have to use new keyword
var locPhotoSchema = new mongoose.Schema({
challengeId: String,
image: String,
main: Number,
});

Setting up an array of collections in MongoDB using Node.js

I am creating a game where, as part of a collection named Game, I am trying to label one of the elements of it. The element in question is supposed to be an array of userNames from another collection. I can't seem to figure out how to access that. Here is what I have in the games collection:
var mongoose = require('mongoose');
var schema = mongoose.Schema;
var ObjectId = schema.ObjectId;
module.exports.Game = mongoose.model('Game', new schema({
id: ObjectId,
gameRoomName: { type: String, required: '{PATH} is required.' },
players: { }
}));
The users collection:
var mongoose = require('mongoose');
var schema = mongoose.Schema;
module.exports.users = mongoose.model('Users', new schema({
userName: {type: String, required: '{PATH} is required.'}
}));
Basically, the usernames for a game will be saved in the Users schema. Then, I'd like to access that and insert it into the Game schema in the players space. I'm imagining it to be something like {type: collection.users}, however, that doesn't seem to be doing the trick.
You can store players as the array of references to Users model
module.exports.Game = mongoose.model('Game', new schema({
.
.
players: [{type: Schema.Types.ObjectId, ref: 'Users'}],
)}
Access later by:
Game.find()
// filter 'players' field
.select('players')
// populate players with only 'username' field
.populate('players', 'username')
.exec(function(err, username) {
// anything with players
});
Long story. You will be good to go after finishing the article
There's a few ways to solve the situation here...but ultimately I think it depends on what data you have readily available at the time you want to add the users into the game object and also how you want to retrieve the data when you need it.
If you have all the usernames cached, whether as objects or just the username itself, it would be more efficient to just add them into the game object.
Example:
var usernamesExample = ["Mike", "Ike", "Clara", "Joe"];
Game.findById(gameIdExample, function(error, foundGame){
// handle errors/checks/etc.
foundGame.players = usernamesExample;
foundGame.save();
})
I personally think this approach is best performance wise. Then again it might not work for your situation, in which case I would need further clarification into how you obtain the username data for the game.

Unique Fields in Mongoose

I'm trying to enforce uniqueness by field on a mongoose model, in an existing database.
const UserSchema = new mongoose.Schema({
email: {
type: String,
required: true,
unique: true,
}
})
Then when I create a user with an email that is already assigned, it passes, and I have 2 users with the same email.
I have read all related SO answers > 2015 and all about dropDups, which is deprecated.
I think I fixed this issue by manually running
db.users.createIndex({email:1}, {unique:true})
However this obviously becomes cumbersome both in development and in production, especially considering the mongoose docs state that the attribute takes care of it:
unique: boolean, whether to define a unique index on this property.
Can someone provide a clear solution to enforcing uniqueness by field on a Mongoose model, considering an existing database and a fresh collection? Thanks
Two user has been created before unique index has been created.So you can insert two users with same email.You can try code below, it make sure all index has been created:
UserModel.on('index', function(error) {
const user1 = new UserModel({
email: '3489'
});
const user2 = new UserModel({
email: '3489'
});
user1.save(console.log);
user2 .save(console.log);
});

confusion in designing db document using mongodb

I use to design 'table' like this
teacher
- id
- name
student
- id
- teacher_id
- name
Just assume 1 teacher can have many students, so I put teacher_id to be able to do join.
But in noSql why should I do multiple document? I can put everything under user and use nested object like
user = {[
id:1,
type:teacher
student:[{
id:321
}]
]}
Imagine my app need to retrieve a list of teacher and student in different tab, still with model I can get the data I need, I just do the filter/manipulation on the client side, correct?
if you use nodejs then i preferred you is to use moongose npm on your node.It use schema and model restriction.Your approach is fine in RDBMS but in mongo you avoid to make joins.
Desgin a schema in this way that match according to your requirements and usage of data availabilty and read or write operations
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var Teachers = new Schema({
//_id: ObjectId,
"name": {
"type": String,
},
"students": [{
name: String
}]
})
module.exports = mongoose.model('Teachers', Teachers);
It avoids your join.it manage all the teachers with their respective students.
You can filter on the server side and send the filtered data to client. It's more efficient.

Nedb Multiple Collection Single Datastore

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); });

Categories

Resources