how to use mongodb indexing in nodejs application - node.js

I am trying to build a search module using mongodb indexing but not sure how to use it on the collection created using mongoose
i.e,
db.books.createIndex({"Title":"text"}) this works fine in mongo shell
where books is a collection which is inside database called bookish
but how to use it in nodejs application where i have few apis calls defined
var express = require('express');
var mongoose = require('mongoose');
router = express.Router();
var cors = require('cors');
module.exports = function (app) {
app.use(router);
};
/*+++++++++++++++++++++++++++++++++++++++++ Defining Model Starts++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
Books = mongoose.model('Books');
/*+++++++++++++++++++++++++++++++++++++++++ Defining Model Stops++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
/*+++++++++++++++++++++++++++++++++++++++++ Router Starts++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
router.route('/api/book/')
.get(function(req,res){
Books.find({},function(err,books){
console.log( req.params.id);
res.send(books);
})
});
router.route('/api/delete/book/:id')
.post(function(req,res){
console.log("delete id"+req.params.id)
Books.findOne({bookId: req.params.id}, function(err,updateRemoveBook) {
updateRemoveBook.isDeleteBook= 0;
updateRemoveBook.save();
res.send(updateRemoveBook);
});
});
router.route('/cerateIndex')
Books.createIndex({"subject":"text","content":"text"})
in this file how to create index on this book ie here books is a refrence of model but create Index should be called on the collection right
i am not able to do like
db.Books.createIndex({"subject":"text","content":"text"})
i am referring this article to perform indexing
http://code.tutsplus.com/tutorials/full-text-search-in-mongodb--cms-24835
not sure how to use it with nodejs application please provide suggestion to how to go about it point some sample which can demonstrate the same

You can create the text indexes using the model schema's index() method:
bookSchema = new mongoose.Schema({"subject": String, "content": String},{"collection": "books"});
bookSchema.index({ "subject": "text", "content": "text" });
Books = mongoose.model('Books', bookSchema);

Related

Get existing document from MongoDB with Mongoose

I have an existing document on MongoDB atlas that I need to get in its entirety. When I try my current code I get a socket timeout, i.e. it keeps buffering.
There is only one document in my collection.
My theory is that the error is in my Mongoose Schema, but I don't know what to put there since I don't want any "filters", I want everything.
The name of the collection in Atlas is Playstation and the id of the document I want to get is: 5f5e2d281386efc27bb3ce45
const express = require('express')
const router = express.Router()
const Playstation = require('../models/playstation')
//Getting All
router.get('/', async (req, res) => {
try {
const playstations = await Playstation.findById("5f5e2d281386efc27bb3ce45")
res.json(playstations)
} catch (err) {
res.status(500).json({ message: err.message })
}
})
module.exports = router;
My schema & model:
const mongoose = require('mongoose')
const playstationSchema = new mongoose.Schema({
})
module.exports = mongoose.model('Playstation', playstationSchema)
I believe the problem is your mongoose schema. What you want is a schemaless collection, since you dont want to define the schema, and you want everything in the document, you can define the collection as schema-less, with strict:false option in your mongoose schema;
Try this:
const mongoose = require('mongoose')
const playstationSchema = new mongoose.Schema({
},{ strict : false })
module.exports = mongoose.model('Playstation', playstationSchema);
You can read more about this option on Mongoose Documentation

Mongo Query Returning Empty Array

I'm a total beginner at this and am using a tutorial to learn the basics of the MEAN stack. I am trying to return the documnents in my database to a web page but am instead receiving an empty array.
I have created a cluster on Mongodb Atlas called mytasklist. Inside here I created a database called mytasklistdb. Inside this I have a table (object) called mytasklistdb.mytasklisttutorial. My understanding of this is limited and so maybe I'm making a huge error somewhere here. I have experience of SQL but not Mongo and so the whole 'clusters' and 'collections' thing is new to me.
Anyway my code is as follows. I took the string for the database connection from the Mongo connection tab.
var express = require('express');
var router = express.Router();
var mongojs = require('mongojs');
var db = mongojs('mongodb+srv://myusername:mypassword#mytasklist-qx0ka.mongodb.net/test?retryWrites=true&w=majority', ['mytasklisttutorial']);
router.get('/tasks', function(req, res, next){
db.mytasklistdb.find(function(err, tasks){
if(err){
res.send(err);
}
res.json(tasks);
});
});
module.exports = router;
My database objects look like this:
_id:5db5f1f31c9d440000c3e7fe
title:"Walk the dog" - this is a string
isDone:false - this is boolean
I'm just getting an empty array but in the tutorial the guy is getting these 'documents'. What am I doing wrong?
EDIT: I realised that the 'tasks' part of the tutorial example was relating to a database called 'tasks'. Mine is called 'mytasklistdb'. I therefore changed this. I also added a parameter with the name of my collection to the line passed in to mongojs.
I have changed my code above to reflect this
The solution was to replace 'task' and 'test' with the name of my db. As follows:
var express = require('express');
var router = express.Router();
var mongojs = require('mongojs');
var db = mongojs('mongodb+srv://James:Noentry1#mytasklist-qx0ka.mongodb.net/mytasklistdb?retryWrites=true&w=majority', ['mytasklisttutorial']);
router.get('/tasks', function(req, res, next){
db.mytasklisttutorial.find(function(err, tasks){
if(err){
res.send(err);
}
res.json(tasks);
});
});
module.exports = router;
My guess is that you are not passing your query, just the callback in the find() method, probably you need to do something like this:
db.tasks.find({},function(err, tasks){
if(err){
res.send(err);
}
res.json(tasks);
});

How does mongoose model connect with mongodb?

I have structured a user collection using mongoose.model().This model exist in seperate file called as model\user.js. The mongodb connection instance (using mongoose) exist in seperate file db\mongoose.js. Both of these files are imported into server.js to work with web application.
var express = require('express');
var bodyParser = require('body-parser');
var {mongoose} = require('./db/mongoose');
var {User} = require('./models/user');
var app = express();
app.use(bodyParser.json());
app.post('/todos', (req, res) => {
var user = new User({
text: req.body.text
});
user.save().then((doc) => {
res.send(doc);
}, (e) => {
res.status(400).send(e);
});
});
app.listen(3000, () => {
console.log('Started on port 3000');
});
module.exports = {app};
The {mongoose} and {User} seems to be a separate entities and model\user.js didn't import ./db/mongoose.js as well . The user model being static content , how does user.save() connects with db and save the document?
First of all let me tell you what is happening in your project.
in Mongoose file:
You have DB connection with Mongoose.
Now Mongoose has your DB connection.
That is the reason it is imported in server.js file.
Secondly, in you model/user.js you have
Declared Schema using Mongoose.
user.save method.
When you use Mongoose here (or any DB related query), it points to your connected DB. Which does not require any explicit connection written in some file.
For more details read Mongoose Docs.
Hope I cleared your thoughts.

modifying results in post find mongoose hook

I am trying to find a way to modify the query results of mongoose.
Below is the self contained model with the post hook
'use strict';
// load the things we need
var mongoose = require('mongoose');
var invoice_db = mongoose.createConnection(config.mongo.url + '/invoiceDB'); //connect to buyer DB
var path = require('path');
// define the schema for our invoice details model
var invoicedetailSchema = new Schema({
//SCHEMA INFO
});
invoicedetailSchema.post('find', function(results){
console.log('POST FIRED')
results = results.filter(function(doc){
return doc.tags.length;
})
})
var InvoiceModel = invoice_db.model('InvoiceDetail', invoicedetailSchema);
// create the model for seller and expose it to our app
promise.promisifyAll(InvoiceModel);
promise.promisifyAll(InvoiceModel.prototype);
module.exports = InvoiceModel;
The find query is working fine and the post is firing but the results are not filtered per the post hook.
How do i go about editing the results before the results are returned.

Mongoose-based app architecture

This is not a concrete app/code question, it's just about common app architecture.
I'm trying to understand proper way to organize my mongoose application. As I'm new to mongoose, that's how I do it now:
core/settings.js
var mongoose = require('mongoose');
exports.mongoose = mongoose;
mongoose.connect('mongodb://localhost/blog');
exports.db = mongoose.connection;
core/models.js
settings = require("./settings");
// post schema
var postSchema = settings.mongoose.Schema({
header: String,
author: String,
text: String
})
//compiling our schema into a Model
exports.post = settings.mongoose.model('post', postSchema)
core/db-layer.js
settings = require("./core/settings");
models = require("./core/models");
exports.function = createAndWriteNewPost(function(callback) {
settings.db.on('error', console.error.bind(console, 'connection error:'));
settings.db.once('open', function callback() {
new models.post({
header: 'header',
author: "author",
text: "Hello"
}).save(function(err, post) {
callback('ok');
});
});
});
routes/post.js
db = reqiure("../core/db.js")
exports.get = function(req, res) {
db.createAndWriteNewPost(function(status){
res.render('add_material', {
//blah blah blah
});
});
};
app.js
var post = require ('routes/post.js')
...
app.get('/post', post.get);
So, this code was extremely simplified (even not tested) just to show my current architecture thoughts. It's not a concrete app, just something like creating an abstract blog post. So thats how it works:
app.js --> routes/post.js <--> core/db-layer.js
|
v
core/models.js <--> core/settings.js
It seems a bit over superfluous for me. Could you suggest more optimal app structure? Thanks.
When I first got into Node.js, Express and Mongoose I struggled with scaling my code.
The intention of my answer is to help someone who's working on more than just a simple blog, but to help with an even larger scalable project.
I am always connected to the database, I do not open and close connections when needed
I use index.js as the root file of a folder, just like we'd do in other languages
models are kept in their own documents, and require()d into the models/index.js file.
routes are similar to models, each route level has a folder, which has an index.js file in turn. So it's easy to arrange something like http://example.com/api/documents/:id. It also makes more sense when one goes through the file structure.
Here's the structure of what I use:
-- app.js
-- models/
---- index.js
---- blog.js
-- mongoose/
---- index.js
-- routes/
---- index.js
---- blog/index.js
-- public/
-- views/
---- index.{your layout engine} => I use Jade.lang
-- methods/
---- index.js => use if you'd rather write all your functions here
---- blog.js => can store more complex logic here
app.js
var db = require('./mongoose'),
express = require('express');
// note that I'm leaving out the other things like 'http' or 'path'
var app = express();
// get the routes
require('./routes')(app);
// I just require routes, without naming it as a var, & that I pass (app)
mongoose/index.js
// Mongoose connect is called once by the app.js & connection established
// No need to include it elsewhere
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/blog');
// I have just connected, and I'm not exporting anything from here
models/index.js
// Logic here is to keep a good reference of what's used
// models
Blog = require('./blog');
// User = require('./user');
// exports
exports.blogModel = Blog.blogModel;
// exports.userModel = User.userModel;
models/blog.js
So for every model that you work on you create a model.js document, and add it in the models/index.js above. As an example I've added a User model but commented it out.
// set up mongoose
var mongoose = require('mongoose');
var Schema = mongoose.Schema,
ObjectId = Schema.ObjectId;
var BlogSchema = Schema({
header: {type: String },
author: {type: String },
text: {type: String },
_id: { type: ObjectId } // not necessary, showing use of ObjectId
});
Blog = mongoose.model('Blog', BlogSchema);
// the above is necessary as you might have embedded schemas which you don't export
exports.blogModel = Blog;
routes/index.js
module.exports = function(app) {
app.get('/', function(req, res) {
// do stuff
});
require('./blog')(app);
// other routes entered here as require(route)(app);
// we basically pass 'app' around to each route
}
routes/blog/index.js
module.exports = function(app) {
app.get('/blog', function(req, res) {
// do stuff
});
require('./nested')(app);
// this is for things like http://example.com/blog/nested
// you would follow the same logic as in 'routes/index.js' at a nested level
}
suggested use
models: for creating the logic that deals with the documents, i.e. creating, updating, deleting, and searching.
routes: minimal coding, only where I need to parse http data, create instances of models, and then I send queries to the relevant model.
methods: for the more complex logic that doesn't directly involve models. As an example, I have an algorithms/ folder where I store all the algorithms that I use in my app.
Hope this provides more clarity. This structure is working wonders for me as I find it easy to follow.
That's pretty much how I go about it, with a few differences:
I don't think you can have the open listener inside your function in the db-layer. What I generally do when using a persistent connection like yours is start the application itself in the db open handler. If you don't want to use persistent connections, use createConnection in the db layer function, and make sure you close it before calling the callback. I am not sure if I am making myself clear. Let me know if you want a code example.
This is more of a general node.js tip, but I keep my database connection string and other configuration in a json file and require it wherever it is needed. You probably won't need another settings.js file after that.
You can also use schema functions (http://mongoosejs.com/docs/api.html#schema_Schema-method) to code some app functionality into your models itself.

Resources