Join 2 collections in mongo with a where clause [duplicate] - database

I have a collection named Releases that holds a subdocument named product.
My collection looks like this:
{
"_id": ObjectId("5b1010e4ef2afa6e5edea0c2"),
"version": "abc",
"description": "<p>abc</p>\n",
"product": {
"_id": ObjectId("5b100c9949f43c6b6f10a93f"),
"name": "Product 1",
"description": "<p>abc</p>\r\n",
"image": "Product 1.png",
"__v": 0
},
"releasedate": ISODate("2018-05-30T00:00:00Z"),
"__v": 0
}
I am trying to find all releases associated to a specific product.
var id = req.body.productId
var query = {'product._id' : id};
Release.find(query)
.select('_id version description product releasedate')
.sort({releasedate: 1 })
.exec()
.then(releases => {
console.log(releases);
res.status(200).json(releases);
})
But it gives me an empty array if i console.log(releases)
I've been stuck with this for a while and asking u guys for help. What am i doing wrong. I read the documentation on https://docs.mongodb.com/manual/tutorial/query-embedded-documents/ and tried to apply that to my code but i cant get it to work.
My Schema looks like this:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var Product = new Schema({
_id: Schema.Types.ObjectId,
name: String,
description: String,
image: String,
});
module.exports = mongoose.model('Product', Product);

You need to change your id from string to mongoose objectId
var id = req.body.productId
var query = {'product._id' : mongoose.Types.ObjectId(req.body.productId)};
Release.find(query)
.select('_id version description product releasedate')
.sort({releasedate: 1 })
.exec()
.then(releases => {
console.log(releases);
res.status(200).json(releases);
})

Related

How to programmatically add to an array in database from frontend React

I basically have this route
app.post("/order/:orderId/:productId", async (req, res) => {
const result = await Order.findByIdAndUpdate(
req.params.orderId,
{
$push: {
products: req.params.productId
}
},
{ new: true }
);
res.send(result);
});
I have two collections, namely Product and Orders. The goal is to get, for instance, a particular Order with id(5ddfc649e1e9e31220ce6a16) , and post a product with id(5de02c4a0ed3160368b9a550) inside an Array field inside this Orders collection. In Postman, I can do that manually by just adding the ObjectIds in the URL like so:
Http://localhost:3000/orders/5ddfc649e1e9e31220ce6a16/5de02c4a0ed3160368b9a550.
and I get this Response :
{
"products": [
"5ddfb388b14c5b41e0607a5e",
"5de02c4a0ed3160368b9a550" // newly added Product
],
"_id": "5ddfc649e1e9e31220ce6a16",
"issuedBy": "issuedBy",
"collectedBy": "collectedBy",
"quantity": 123,
"createdAt": "2019-11-28T11:48:40.500Z",
"updatedAt": "2019-11-28T11:59:51.659Z",
"__v": 0
}
My challenge is, how do I do this programmatically from the UI(Reactjs) side?
// Product Schema
const mongoose = require("mongoose");
const ProductSchema = new mongoose.Schema(
{
name: String,
description: String,
price: Number,
quantity: Number,
supplier: String
},
{ timestamps: true }
);
module.exports = mongoose.model("Product", ProductSchema);
// Orders Schema
const mongoose = require("mongoose");
const OrderSchema = new mongoose.Schema(
{
issuedBy: String,
collectedBy: String,
quantity: Number,
products: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "Product",
required: true
}
]
},
{ timestamps: true }
);
module.exports = mongoose.model("Order", OrderSchema);
I would really appreciate any suggestion or a sample code snippet
I think what you are looking for is, you need to hit this API from your front end i.e. React app.
http://localhost:3000/orders/<order-id-here>/<product-id-here>
And then supply the dynamic value for your order id and product id.
You can hit api using fetch. More info
You can simply take some variables in your front end app. As I don't know how your order id and product id are being generated so you need to check on that and then something like,
let orderId = someValue
let productId = someOtherValue
let url = "http://localhost:3000/orders/"+orderId+"/"+productId
But I think the concern would be GET and POST method. Right now you have app.post but the params are in URL so instead you should go for GET method i.e. app.get

mongoose + nodejs push array to database

I'm new to NodeJS + Mongoose and having trouble pushing an array to my database via mongoose.
I have the following schema:
const StudentSchema = mongoose.Schema({
name: {
type: String
},
quizzes: [{
quiz: String,
answers: []
}]
});
What I'm trying to do is have an array of quiz objects in which the quiz number is shown and the array of answers for that particular quiz.
When I create a new user, the student object looks like this in mongoose:
{
"_id" : ObjectId(id here),
"name" : "John",
"quizzes" : [ ],
"__v" : 0
}
The function I'm using to update the quiz array:
module.exports.addQuiz = function(student_id, answers, callback){
Student.findByIdAndUpdate(
student_id,
{$push: {"quizzes": {answers: answers}}},
{safe: true, upsert: true},
function(err, model) {
console.log(err);
}
);
}
And this is my route which calls the function whenever the endpoint is hit with a student_id, which will then be used to find the student and push to the array
router.post('/quiz/:student_id', (req, res, next) => {
var student_id = req.params.id;
var answers = req.body.answers;
Student.addQuiz(student_id, answers, (err, answers) => {
//error handling
})
});
I'm trying to test this by sending a post request to /quiz/:student_id with an id of a student in my database with the following JSON sent in the body:
[{
"quiz": "Quiz 1",
"answers": ["Answer 1", "Answer 2"]
}]
Although when I try this it ends up getting hung somewhere and the request never completes - I also get a "null" in the console.
Can anyone help me out? Thank you.

How to insert record automatically in mongodb (nodejs, express, mongoose)

I am working on a team-based project. I created a new collection with some records (inserted manually). Is there any script or code to insert these records automatically from within the code, so that my when my colleague will work they do not need to insert those records again.
Code:
var mongoose = require("mongoose");
var Schema = mongoose.Schema;
var ServiceCategoryTypeSchema = new Schema({
_id: {type: String},
name:String
}, {
collection:'service_category_type',
timestamps:{createdAt:'created_at', updatedAt:'updated_at'}
}
);
module.exports = {
getModel: function(db){
return db.model("ServiceCategoryType", ServiceCategoryTypeSchema)
},
schema:ServiceCategoryTypeSchema
};
This is the record, I am thinking to add automatically,
{
"_id" : "Inventory",
"name" : "Inventory"
}
{
"_id" : "Non-inventory",
"name" : "Non-inventory"
}
{
"_id" : "Service",
"name" : "Service"
}
When you have your model in, say, YourModel, then you should be able to save your data that you have in, say, yourData with something like this:
new YourModel(yourData).save(function (error, data) {
// handle errors, log success etc.
});
You can do it for as many pieces of data as you want.
When you populate the database with some data it may be a good idea to first check if the database is not populated yet.
Example
Here is a working example program that saves such data - I changed the database and collection names so that you won't mess with your real database when you run it:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var P = mongoose.Promise = require('bluebird');
mongoose.connect('mongodb://localhost/poptest');
var TestModel = mongoose.model('TestModel', new Schema({
_id: String,
name: String
}, {
collection: 'testcollection',
timestamps: {createdAt: 'created_at', updatedAt: 'updated_at'}
}
));
var sampleData = [
{_id: "Inventory", name: "Inventory"},
{_id: "Non-inventory", name: "Non-inventory"},
{_id: "Service", name: "Service"}
];
P.all(sampleData.map(i => new TestModel(i).save()))
.then(() => console.log('Data saved'))
.catch((err) => console.log('Error: ' + err))
.finally(process.exit);
You need to install mongoose and bluebird for it to work:
npm i mongoose bluebird
It creates 3 documents in the poptest database on localhost. You can verify it by running:
mongo poptest
and querying the testcollection collection:
db.testcollection.find();
You should get something like:
> db.testcollection.find().pretty();
{
"_id" : "Inventory",
"updated_at" : ISODate("2016-09-14T16:13:37.374Z"),
"created_at" : ISODate("2016-09-14T16:13:37.374Z"),
"name" : "Inventory",
"__v" : 0
}
{
"_id" : "Non-inventory",
"updated_at" : ISODate("2016-09-14T16:13:37.377Z"),
"created_at" : ISODate("2016-09-14T16:13:37.377Z"),
"name" : "Non-inventory",
"__v" : 0
}
{
"_id" : "Service",
"updated_at" : ISODate("2016-09-14T16:13:37.377Z"),
"created_at" : ISODate("2016-09-14T16:13:37.377Z"),
"name" : "Service",
"__v" : 0
}
This solution worked for me: https://github.com/Automattic/mongoose/issues/6326
'use strict'
const mongoose = require('mongoose')
const uri = 'mongodb://localhost/test'
const db = mongoose.createConnection(uri)
const Schema = mongoose.Schema
const testSchema = new Schema({
name: String,
age: Number
})
const Test = db.model('test', testSchema)
const test = new Test({ name: 'Billy', age: 31 })
db.once('connected', function (err) {
if (err) { return console.error(err) }
Test.create(test, function (err, doc) {
if (err) { return console.error(err) }
console.log(doc)
return db.close()
})
})

MEAN Mongodb replace collection and create documents

So i have a schema like that:
var article = new mongoose.Schema({
title : String,
comments : [{
pe: mongoose.Schema.Types.ObjectId,
ref: 'Comment'
}]
});
and:
var comment = new mongoose.Schema({
created : Date,
text : String
});
now i have my small angular application, when i retrieve with my API and article i get something like:
{
title : "please help me"
comments : []
}
now on the front end I push some comments and the new object is:
{
title : "please help me"
comments : [{
text : "Now, go f**k yourself",
date : "1 January 1970 00:00:00 UTC."
}]
}
when i call the API and I update the document, I would like that mongo would Create the sub-object comments by himself, is there a way ?
Should it do it automatically ?
I would write a article schema this way (disclaimer: I haven't tried mongoose):
var article = new mongoose.Schema({
_id: String // or mongodb.ObjectId? I'm not sure.
title : String,
comments : [{
_id: String // this field is not nessesary
text: String,
date: String
}]
});
var comment = new mongoose.Schema({
created : Date, // created or date?
text : String
});
When you retrieve with you api, you'll get something like:
{
"_id": "ndrjgnd..fesf",
"title": "grdgrdgr",
comments: [ {"text": "hello", "created": "2016:...:"}, ... , ]
}
Then you can push new comments from front end:
{
"articleId": "ndrjgnd..fesf", // this is important.
"text": "balabala"
}
And update db: db.article.update( {_id: ariticleId}, {$push: newComment})

PouchDB startkey endkey not returning docs

I seem to have an issue in retrieving a selected few documents from a PouchDB using startkey and endkey. I need to get the documents back with key starting with "profile" (in this example profile41 & profile48).
When using the chrome PouchDB extension, this works fine when doing a query using startkey:"profile" and endkey:"profile\0ffff", but for some reason, this doesn't work when running my code (angular/ionic).
My code returns an empty doc list. When I set the startkey:"profile41" and endkey:"profile41" I do get the doc back, so I know it connects and can retrieve documents from the DB.
PS: First use of PouchDB, so I might have overlooked something simple here.
Some documents in my db
{
"_id": "animaltypes",
"_rev": "7-e413c314272a62a6a14ed293f5f934cf",
"value": {
"rev": "7-e413c314272a62a6a14ed293f5f934cf"
},
"key": "animaltypes"
}
{
"_id": "profile41",
"_rev": "3-f4065b825d304d79479e3576409ce744",
"value": {
"rev": "3-f4065b825d304d79479e3576409ce744"
},
"key": "profile41"
}
{
"_id": "profile48",
"_rev": "3-5e62a6e33f022a8ac30d46b80126dedd",
"value": {
"rev": "3-5e62a6e33f022a8ac30d46b80126dedd"
},
"key": "profile48"
}
My javascript that retrieves docs
this.getData = function(keystart,keyend){
var deferred = $q.defer();
localDB.allDocs({include_docs: true,
descending: true,
startkey:keystart,
endkey:keyend}, function(err, doc) {
if (err) {
deferred.reject(err);
} else {
var rows = [];
for (var x in doc.rows) {
rows.push(doc.rows[x].doc.data);
}
deferred.resolve(rows);
}
});
return deferred.promise;
};
This returns an empty array with the following params
startkey = "profile"
endkey = "profile\0ffff"
This returns the correct single doc when parameters are set to
startkey = "profile41"
endkey = "profile41"
If you want to use "descending:true" you have to change the order of startkey and endkey.
Indeed, if you don't use "descending:true" you B-Tree looks like that:
1- animaltypes
2 - profile41
3 - profile48
startkey="profile" will be between id 1 and id 2
endkey="profile\0ffff" will be after id 3
In result you will have 2 records
If you use "descending=true" you B-Tree looks like that:
1- profile48
2 - profile41
3 - animaltypes
startkey="profile" will be between id 2 and id 3
endkey="profile\0ffff" will be after id 2 and id 3
in result you will have 0 record.

Resources