using module.exports in node to have better structure - javascript

var mongoose = require('mongoose');
var genreSchema = mongoose.Schema({
name:{
type: String,
required: true
},
create_date:{
type: Date,
default: Date.now
}
});
var Genre = module.exports = mongoose.model('Genre',genreSchema);
//Get Grenres
module.exports.getGenres = function (callback, limit) {
Genre.find(callback).limit(limit);
}
//Add Genre
module.exports.addGenre = function (genre, callback) {
Genre.create(genre, callback);
}
Above code is working but I felt the code is ugly because I have to write so many times of module.exports. How to simplify above code?

You can have a single object assigned to module.exports like below -
var Genre = mongoose.model('Genre',genreSchema);
//Get Grenres
var getGenres = function (callback, limit) {
Genre.find(callback).limit(limit);
}
//Add Genre
var addGenre = function (genre, callback) {
Genre.create(genre, callback);
}
module.exports = {
getGenres : getGenres,
addGenres : addGenre
};

Related

how to update 2nd schema using node js (mongdb)

I am trying to update my 2nd schema which having reference in first schema
ownerSchema.js
var ownerSchema = Schema({
fname : String,
lname : String,
shopPlace : {
type: Schema.Types.ObjectId,
ref: 'Shop'
}
});
var Owner = mongoose.model('Owner', ownerSchema);
shopSchema.js
var shopSchema = Schema({
shopName : String,
location : String,
startDate : Date,
endDate : Date
});
var Shop = mongoose.model('Shop', shopSchema);
so I am trying to update my schema like this
const update = async (req, res) => {
const { id } = req.params;
let update = {};
if (req.body.fname) update.fname = req.body.fname;
if (req.body.lname) update.lname = req.body.lname;
if (req.body.shopPlace.shopName) update.shopPlace.shopName = req.body.shopPlace.shopName;
if (req.body.shopPlace.location) update.shopPlace.location = req.body.shopPlace.location;
let newOwmer = new Owner.updateOne(
{ ownerId: id },
{
$set: update,
},
{ runValidators: true }
);
};
I am trying to update shop but its not working and where am i wrong i dont know
const update = async (req, res) => {
const { id } = req.params;
let update = {};
let updateShop = {}
if (req.body.fname) update.fname = req.body.fname;
if (req.body.lname) update.lname = req.body.lname;
if (req.body.shopPlace.shopName) updateShop.shopPlace.shopName = req.body.shopPlace.shopName;
if (req.body.shopPlace.location) updateShop.shopPlace.location = req.body.shopPlace.location;
// get shopPlace _id from Owner
const { shopPlace } = await Owner.findOneAndUpdate(
{ _id: id },
{
$set: update,
},
{ new:true}
);
// here you must have the document you just updated. Just recover the id of the shop to modify it in turn
// update shop
let newShop = await Shop.findOneAndUpdate(
{ _id: shopPlace },
{
$set: updateShop,
},
{new:true}
);
};

How to create incremental custom ID in mongoDB

How can I create a incremental custom id in mongoDB.
Example:
let type = 'x'
let inputCounts = {}
function something(type){
inputCounts[type] = (inputCounts[type] || 0) + 1;
return `custom-id-${inputCounts[type]}`
}
something(type)
Like this what the above function does, I want something that I can do directly in code for mongoDB
So that I can get a customID based on different type, Because like this when I will restart the server the object will get reset.
Thank you
Thank you for the help mates.
Found the solution so thought will share.
Create a counter collection as
db.createCollection("counters")
or
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const Counter = new Schema(
{
_id: {type: Schema.Types.ObjectId},
sequence_value: {type: Number}
},
{
timestamps: true
}
);
Counter.index({_id: 1}, {unique: true});
var Counter = mongoose.model('Counter', Counter);
module.exports = Counter;
Then create a JS Function :
function getNextSequenceValue(id) {
return new Promise((resolve, reject) => {
Counter.findOneAndUpdate({_id: ObjectId(id)}, {$inc: {sequence_value: 1}, upsert: true}).exec(function(
err,
counter
) {
if (err) return reject(err);
return resolve(counter.sequence_value);
});
});
}
Then you can get the sequence_value based on id passed.
let custom_id = await getNextSequenceValue(id)
custom_id will give you the value in sequential order

Javascript mongoose callback function when set data

Hello my problem is when I post base 64 images, I want to return a photo URL that's inside of my schema set return value
It always returns null and not set to photoUrl column
here is my schema
const ProductSchema = new Schema({
_id: {
type: Schema.Types.ObjectId,
default: require('mongodb').ObjectID
},
country: {
type: String,
required: [true, "country can't be null"]
},
photoUrl: {
type: String,
set: setImage
}
})
this my setter function
function setImage(base64) {
return uploadImage(base64,'/storage/products/');
}
and this is my uploadImage function on another page
const fs = require('fs');
const keys = require('../config/keys');
const mkdirp = require('mkdirp');
const uuidv4 = require('uuid/v4');
module.exports = {
get: function() {
let a = "Hello Node World!!!";
return a;
},
uploadImage: function(base64,storageURI,callback) {
const storagePathURI = '.' + storageURI;
mkdirp(storagePathURI, function (err) {
if (!err) {
var base64Data = base64.replace(/^data:image\/png;base64,/, "");
fs.writeFile(storagePathURI + uuidv4() + '.png', base64Data, 'base64')
return keys.baseStorageURI + storageURI + uuidv4() + '.png';
}
});
}
}
how can I map this URL to my photoUrl column when I insert or update the object?

Mongoose returns Mongo object, but can't access property on it

In my simple Node/Mongo/Mongoose setup, I have a function that calls the server to see what the highest ID I'm using currently is, and return the next ID. This function takes as a callback the functionality that creates a new Game.
Weird: The logger.log as it appears below outputs
result { _id: 555d83d5bb0d4e3c352d896f, gameId: 'NaN' }
but when I change the logger to
logger.log("result", result.gameId);
the output is
result { _id: 555d83d5bb0d4e3c352d896f, gameId: 'NaN' }
which makes no sense. Clearly that property is there!
Here is my code
var createGame = function(gameNickname, callback){
nextGameId(function(nextId){
var newgame = new models.Game({
"gameId": Number(nextId),
"gameNickname": gameNickname
});
newgame.save(function(result, game){
callback(result + nextId);
});
});
};
var nextGameId = function(callback){
var games = models.Game.find({}, {gameId: 1});
games.sort('-gameId').limit(1) //get the highest number roundId and add 1 to it
.exec(function (err, result) {
if (err) logger.log(err);
if (result === null){
callback(0);
}
else{
logger.log("result", result);
callback(result.gameId);
}
});
};
i recommend you use autoincrement mongoose plugin, somthing like this
var mongoose = require('mongoose');
var autoIncrement = require('mongoose-auto-increment');
var connection = mongoose.createConnection("mongodb://localhost/db");
autoIncrement.initialize(connection);
var GameSchema = {
"gameId": {type: Number},
"gameNickname": {type: String}
}
GameSchema.plugin(autoIncrement.plugin, { model: 'Game', field: 'gameId' });
mongoose.model('Game', GameSchema);
after this you can save your game with autoinc, for example:
var Game = mongoose.model('Game');
function createNewGame(nickname){
return new Game({gameNickname: nickname}).save(function(err, res){
console.log(res);
//some code...
})
}
after execute this code you should have somnthing like this:
{
_id: "555d83d5bb0d4e3c352d896f",
gameNickname: "nickname",
gameId: 1
}

Mongoose findOne in stream callback not executed

When I execute a findOne query to a collection that is different than that of the surrounding stream, it doesn't really execute the callback (does 1 or 2). Here is my code:
schema.js:
'use strict';
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
var AutocompleteSchema = new Schema({
nGram: String,
locations: [{ type: Schema.Types.ObjectId, ref: 'Location' }]
});
module.exports = mongoose.model('Autocomplete', AutocompleteSchema);
ingest.js:
var Autocomplete = require('./schema');
var nGramAPI = require('ngram');
var cache = [];
function storeNGram(input, location) {
if(cache.indexOf(input) === -1) {
cache.push(input);
Autocomplete
.findOne({ nGram: input })
.populate('locations')
.exec(function (err, nGram) {
console.log(nGram);
if(!nGram) {
var newAutocomplete = {
nGram: input,
locations: [location._id]
};
Autocomplete.create(newAutocomplete, function(err, created) {
cache.splice(cache.indexOf(input), 1);
});
}
else {
nGram.locations.push(location._id);
sortLocations(nGram);
location.save(function(err, saved){
cache.splice(cache.indexOf(input), 1);
});
}
});
}
else {
setTimeout(function() {
storeNGram(input, location);
}, 100);
}
}
exports.ingest = function() {
console.log("Building nGrams");
var stream = Location.find().stream();
stream.on('data', function (location) {
var length = location.dispName.length > 20 ? 20 : location.dispName.length;
for(var i = 1; i <= length; i++) {
_.each(nGramAPI(i)(location.dispName), function(nGram) {
storeNGram(nGram, location);
});
}
});
}
When I execute the Autocomplete.findOne on its own outside of the stream it queries properly, but when inside it fails. Any suggestions?

Categories

Resources