why mongoose populate() request does not work? - mongodb

I try to populate some data from other collection to an other collection.i had googled the search and also i follow the tutorial step by step but the population had fail.any help is appreciate friends. this is the code:
router.get("/", passport.authenticate("jwt", {session: false}), (req, res)=> {
const errors = {};
Profile.findOne({user: req.user.id})
.then(profile => {
if (!profile) {
errors.noprofile = "there is no profile for this user"
return res.status(404).json(errors);
}
res.json(profile);
}).catch(err=> res.status(404).json(err))
});
// #route POST api/profile
//#desc Create or edit user profile
//#access Private
router.get("/", passport.authenticate("jwt", {session: false}), (req, res)=> {
const {errors, isValid} = validateProfileInput(req.body);
//Check validation
if(!isValid) {
return res.status(400).json(errors);
}
// Get profile data
const profileData = {};
profileData.user = req.user.id;
if(req.body.handle) {
profileData.handle = req.body.handle
};
if(req.body.company) {
profileData.company = req.body.company
};
if(req.body.website) {
profileData.website = req.body.website
};
if(req.body.location) {
profileData.location = req.body.location
};
if(req.body.status) {
profileData.status = req.body.status
};
if(typeof req.body.skills !== 'undefined') {
profileData.skills = req.body.skills.split(',');
}
//social
profileData.social = {};
if(req.body.youtube) {
profileData.social.youtube = req.body.youtube
};
if(req.body.twitter) {
profileData.social.twitter = req.body.twitter
};
if(req.body.facebook) {
profileData.social.facebook = req.body.facebook
};
if(req.body.instagram) {
profileData.social.instagram = req.body.instagram
};
Profile.findOne({user: req.user.id})
.populate(
"user",
["name, avatar"]
)
this is the result that I get from the postman :
"_id": "62ee1058ceb295ccdfedffce",
"user": "62e6825958870d3db69d2da5",
"handle": "pablo",
"status": "developper",
"skills": [
"design web"
],
and the correct result must be :
"_id": "62ee1058ceb295ccdfedffce",
"user": {"_id": "62e6825958870d3db69d2da5",
"name": "pablo",
"avatar": "//www.gravatar.com/avatar/1ffsrenbdgeajks-ghsdereys1dkkdhddbc"
}
"handle": "pablo",
"status": "developper",
"skills": [
"design web"
],

Related

One to one with populate mongoose not working

I'm new to mongoose and mongodb.
I have two collection (cart and produk)
1 cart have 1 produk, and I get the cart and populate the product but is not show the data relations.
Here the code:
routing
router.route('/relations/:app_id')
.get(cartController.relation);
model (cartModel)
var mongoose = require('mongoose');
var cartSchema = mongoose.Schema({
app_id: {
type: String,
required: true
},
product_id: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Produk'
},
qty: Number
});
var collectionName = 'cart';
var Cart = module.exports = mongoose.model('Cart', cartSchema, collectionName);
module.exports.get = function (callback, limit) {
Cart.find(callback).limit(limit);
}
model (produkModel)
var mongoose = require('mongoose');
// Setup schema
var produkSchema = new Schema({
name: {
type: String,
required: true
},
stok: Number
});
// Export Cart model
var collectionName = 'produk';
var Produk = module.exports = mongoose.model('Produk', produkSchema, collectionName);
module.exports.get = function (callback, limit) {
Produk.find(callback).limit(limit);
}
controller (cartController)
Cart = require('../model/cartModel');
exports.relation = function (req, res) {
const showCart = async function() {
const carto = await Cart.find().select('app_id product_id qty').populate("produk");
return carto;
};
showCart()
.then(cs => {
return apiResponse.successResponseWithData(res, "Operation success", cs);
})
.catch(err => console.log(err));
};
// Result
{
"status": 1,
"message": "Operation success",
"data": [
{
"_id": "60af72022d57d542a41ffa5a",
"app_id": "CvR4dTTjC7qgr7gA2yoUnIJnjRXaYokD6uc2pkrp",
"qty": 1,
"product_id": "60112f3a25e6ba2369424ea3"
},
{
"_id": "60b020536ccea245b410fb38",
"app_id": "CvR4dTTjC7qgr7gA2yoUnIJnjRXaYokD6uc2pkrp",
"product_id": "603f5aff9437e12fe71e6d41",
"qty": 1
}
]
}
expecting result
{
"status": 1,
"message": "Operation success",
"data": [
{
"_id": "60af72022d57d542a41ffa5a",
"app_id": "CvR4dTTjC7qgr7gA2yoUnIJnjRXaYokD6uc2pkrp",
"qty": 1,
"product_id": {
"_id": "60112f3a25e6ba2369424ea3",
"name": "snack"
}
},
{
"_id": "60b020536ccea245b410fb38",
"app_id": "CvR4dTTjC7qgr7gA2yoUnIJnjRXaYokD6uc2pkrp",
"product_id": {
"_id": "603f5aff9437e12fe71e6d41",
"name": "snack"
}
"qty": 1
}
]
}
what I miss ???
Thanks for your help
You need to pass the path to populate or an object specifying parameters to .populate(). So in this case, Your code should be:
const carto = await Cart.find().select('app_id product_id qty').populate("product_id");

Problem setting up node js server to listen for webhook and post to database

Good morning everyone, I'm having a bit of a struggle setting up a server to listen for webhook data and post it to a database. I'm mostly front-end, so some of this is a bit new for me. So I have a deli website that i built on snipcart. I have a receipt printer that queries an api and prints out new orders. So what I'm wanting is a server to listen for the webhook and store the info in a database. I've got it where it listens for the webhook correctly, but it refuses to post to the database. Here's the code in the app.js file.
'use strict';
require('./config/db');
const express = require('express');
const bodyParser = require('body-parser');
const fetch = require('node-fetch');
const app = express();
var routes = require('./api/routes/apiRoutes');
routes(app);
let orderToken;
app.use(bodyParser.urlencoded({extended:true}));
app.use(bodyParser.json());
app.listen(process.env.PORT || 8080);
app.post('/hook', (req, res) => {
orderToken = req.body.content.token;
console.log(orderToken);
const secret = "snipcart api key";
const apiFetch = async function(){
};
let buffered = new Buffer.from(secret);
let base64data = buffered.toString('base64');
const start = async function(){
const request = await fetch('https://app.snipcart.com/api/orders/'+orderToken, {
headers: {
'Authorization': `Basic ${base64data}`,
'Accept': 'application/json'
}
});
const result = await request.json();
console.log(result);
};
start();
res.status(200).end();
});
app.get('/', (req, res) => {
res.send('hello world')
});
Here's the code in my apiController.js file
const mongoose = require('mongoose'),
Order = mongoose.model('apiModel');
// listAllOrders function - To list all orders
exports.listAllOrders = (req, res) => {
api.find({}, (err, api) => {
if (err) {
res.status(500).send(err);
}
res.status(200).json(api);
});
};
// createNewOrder function - To create new Order
exports.createNewOrder = (req, res) => {
let newApi = new api (req.body);
newApi.save((err, api) => {
if (err) {
res.status(500).send(err);
}
res.status(201).json(api);
});
};
// deleteOrder function - To delete order by id
exports.deleteOrder = async ( req, res) => {
await api.deleteOne({ _id:req.params.id }, (err) => {
if (err) {
return res.status(404).send(err);
}
res.status(200).json({ message:"Order successfully deleted"});
});
};
and my apiModel.js file
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const ApiSchema = new Schema({
customerName: {
type:String,
required:true
},
customerPhone: {
type:String,
required:true
},
name: {
type:String,
required:true
},
orderNumber: {
type:String,
required:true
},
price: {
type:String,
required:true
},
customFields: {
type:Array,
required:false
},
});
module.exports = mongoose.model("apiModel", ApiSchema);
apiRoutes.js
module.exports = function(app){
var orderList = require('../controllers/apiController');
app
.route('/orders')
.get(orderList.listAllOrders)
.post(orderList.createNewOrder);
app
.route('/order/:id')
.delete(orderList.deleteOrder);
};
and my db.js
const mongoose = require("mongoose");
//Assign MongoDB connection string to Uri and declare options settings
var uri = "<mongodb atlas info>
retryWrites=true&w=majority";
// Declare a variable named option and assign optional settings
const options = {
useNewUrlParser: true,
useUnifiedTopology: true
};
// Connect MongoDB Atlas using mongoose connect method
mongoose.connect(uri, options).then(() => {
console.log("Database connection established!");
},
err => {
{
console.log("Error connecting Database instance due to:", err);
}
});
and here's a sample response that I need to place into the database
{
"token": "93c4604e-35ac-4db7-b3f1-2871476e9e6a",
"creationDate": "2013-10-22T20:54:40.377Z",
"modificationDate": "2013-10-22T20:55:45.617Z",
"status": "Processed",
"paymentMethod": "CreditCard",
"invoiceNumber": "SNIP-1427",
"email": "geeks#snipcart.com",
"cardHolderName": "Geeks Snipcart",
"creditCardLast4Digits": "4242",
"billingAddressName": "Geeks Snipcart",
"billingAddressCompanyName": "Snipcart",
"billingAddressAddress1": "4885 1ere Avenue",
"billingAddressAddress2": null,
"billingAddressCity": "Quebec",
"billingAddressCountry": "CA",
"billingAddressProvince": "QC",
"billingAddressPostalCode": "G1H2T5",
"billingAddressPhone": "1-877-301-4813",
"notes": null,
"shippingAddressName": "Geeks Snipcart",
"shippingAddressCompanyName": "Snipcart",
"shippingAddressAddress1": "4885 1ere Avenue",
"shippingAddressAddress2": null,
"shippingAddressCity": "Quebec",
"shippingAddressCountry": "CA",
"shippingAddressProvince": "QC",
"shippingAddressPostalCode": "G1H2T5",
"shippingAddressPhone": "1-877-301-4813",
"shippingAddressSameAsBilling": true,
"finalGrandTotal": 287.44,
"shippingFees": 10,
"shippingMethod": "Shipping",
"items": [
{
"uniqueId": "1aad3398-1260-419c-9af4-d18e6fe75fbf",
"id": "1",
"name": "Un poster",
"price": 300,
"quantity": 1,
"url": "http://snipcart.com",
"weight": 10,
"description": "Bacon",
"image": "",
"customFieldsJson": "[]",
"stackable": true,
"maxQuantity": null,
"totalPrice": 300,
"totalWeight": 10
},
...
],
"taxes": [
{
"taxName": "TPS",
"taxRate": 0.05,
"amount": 12.5,
"numberForInvoice": ""
},
{
"taxName": "TVQ",
"taxRate": 0.09975,
"amount": 24.94,
"numberForInvoice": ""
},
...
],
"rebateAmount": 0,
"subtotal": 310,
"itemsTotal": 300,
"grandTotal": 347.44,
"totalWeight": 10,
"hasPromocode": true,
"totalRebateRate": 20,
"promocodes": [
{
"code": "PROMO",
"name": "PROMO",
"type": "Rate",
"rate": 20,
},
...
],
"willBePaidLater": false,
"customFields": [
{
"name":"Slug",
"value": "An order"
},
...
],
"paymentTransactionId": null,
}
I dont need all the info placed in the database, just a few key items, like customer name, phone number and the order info. but if there's more than one item in the order, I need it to take that into account and add all the items in the order. here is the docs for the printer that i'm needing to integrate https://star-m.jp/products/s_print/CloudPRNTSDK/Documentation/en/index.html Would appreciate any help that you all can give me. Thanks!
Snipcart will send the webhook to you endpoint for different events. I would suggest you to first filter the event by eventName, because you want to listen for only the order.completed event. After that from the body of the request message, you can extract the items that will be in the req.body.content.items. You can take from the available info what you want and store only that in the database.
Try this:
app.post('/hook', (req, res) => {
if (req.body.eventName === 'order.completed') {
const customer_name = req.body.content.cardHolderName;
const customer_phone req.body.content.billingAddressPhone;
const order_number = req.body.content.invoiceNumber;
let items = [];
req.body.content.items.forEach((item) => {
items.push({
name: item.name,
price: item.price,
quantity: item.quantity,
id: item.uniqueId
});
})
// Now store in database
apiFetch.create({
customerName: customer_name,
customerPhone: customer_phone
name: customer_name,
orderNumber: order_number
customFields: items
}).then(()=>{
res.status(200).json({success:true});
}, (error)=>{
console.log('ERROR: ', error);
})
}
};

Promise all in typescript does not resolve all

In my code I need to update the model
{
"customerCode": "CUS15168",
"customerName": "Adam Jenie",
"customerType": "Cash",
"printPackingSlip": "true",
"contacts": [
{
"firstName": "Hunt",
"lastName": "Barlow",
"email": "huntbarlow#volax.com",
"deliveryAddress": "805 Division Place, Waumandee, North Carolina, 537",
},
{
"firstName": "Barlow",
"lastName": "Hunt",
"email": "huntbarlow#volax.com",
"deliveryAddress": "805 Division Place, Waumandee, North Carolina, 537",
}
],
"deliveryAddress": [
{
"addressName": "Postal",
"addressType": "postal address",
"addressLine1": "plaza street",
"addressLine2": "broome street",
"suburb": "Guilford",
"city": "Oneida",
"state": "Colorado",
"postalCode": "3971",
"country": "Belarus",
"deliveryInstruction": "test delivery address"
},
{
"addressName": "Physical",
"addressType": "physical address",
"addressLine1": "plaza street",
"addressLine2": "broome street",
"suburb": "Guilford",
"city": "Oneida",
"state": "Colorado",
"postalCode": "3971",
"country": "Belarus",
"deliveryInstruction": "test delivery address"
}
]
}
I used promise all to achieve that. In postman, I send this object, but first it needs to add the customer, the contact array and then delivery address array. I did it as follows.
public async createCustomer(customer: CustomerDTO): Promise<CustomerDTO> {
let deliveryAddress = [];
let contacts = [];
let customerDto = new CustomerDTO();
customerDto.customerCode = customer.customerCode;
customerDto.tenantId = customer.tenantId;
if (customer.contacts.length > 0) {
customer.contacts.map((element => {
contacts.push(element);
}));
customer.contacts.length = 0;
}
if (customer.deliveryAddress.length > 0) {
customer.deliveryAddress.map((element => {
deliveryAddress.push(element);
}));
customer.deliveryAddress.length = 0;
}
const createdCustomer = await this.customerRepo.updateOrCreateCustomer(customer);
let updatedAddress = deliveryAddress.map(async (address: CustomerDeliveryAddressDto) => {
return await this.customerRepo.updateDeliveryAddress(address, customerDto, address._id);
});
let updatedContacts = contacts.map(async (contact: CustomerContactsDto) => {
return await this.customerRepo.createOrUpdateContactList(contact, customerDto, contact._id);
});
return Promise.all([updatedAddress, updatedContacts]).
then((results: [Promise<boolean>[], Promise<boolean>[]]) => {
console.log(results);
return this.customerRepo.getLastUpdatedCustomer();
}).
then((result) => {
return result;
}).
catch(e => {
console.error(e);
return e;
});
}
In customerRepository
public async updateDeliveryAddress(deliveryAddressDto: CustomerDeliveryAddressDto, customerDto: CustomerDTO, deliveryAddressId: string): Promise<boolean> {
const customerToBeUpdated = await this.model.findOne({
customerCode: customerDto.customerCode,
tenantId: customerDto.tenantId
});
if (customerToBeUpdated !== null) {
if (deliveryAddressId != null || deliveryAddressId != undefined) {
const result = await this.model.findOneAndUpdate({ _id: customerToBeUpdated._id, deliveryAddress: { $elemMatch: { _id: deliveryAddressId } } },
{
$set: {
//code here
}
},
{ 'new': true, 'safe': true, 'upsert': true });
if (result){
return true;
}
} else {
const result = await this.model.findOneAndUpdate({ _id: customerToBeUpdated._id },
{
$push: { deliveryAddress: deliveryAddressDto }
},
{ 'new': true, 'safe': true, 'upsert': true }
);
if (result) {
return true;
}
}
} else {
return false;
}
}
The problem is that it does not resolve all the methods when it goes to promise all method and I need to get the last updated customer, but it gives the result DeliveryAddress and contacts with empty arrays. Customer document on mongodb is updated as needed.
You need to pass the promises directly in a flat array.
Promise.all on MDN
If the iterable contains non-promise values, they will be ignored, but still counted in the returned promise array value (if the promise is fulfilled)
You can do this easily using the spread operator.
let updatedAddress = deliveryAddress.map(async (address: CustomerDeliveryAddressDto) => {
return await this.customerRepo.updateDeliveryAddress(address, customerDto, address._id);
});
let updatedContacts = contacts.map(async (contact: CustomerContactsDto) => {
return await this.customerRepo.createOrUpdateContactList(contact, customerDto, contact._id);
});
// need to give a flat array to Promise.all, so use the `...` spread operator.
return Promise.all([...updatedAddress, ...updatedContacts]).then(/* ... */
Also, since you are already using async / await, no reason you cannot await the Promise.all call.
const results = await Promise.all([...updatedAddress, ...updatedContacts]);
console.log(results);
return this.customerRepo.getLastUpdatedCustomer();
You can also nest Promise.all
let updatedAddress = Promise.all(deliveryAddress.map(async (address: CustomerDeliveryAddressDto) => {
return await this.customerRepo.updateDeliveryAddress(address, customerDto, address._id);
}));
let updatedContacts = Promise.all(contacts.map(async (contact: CustomerContactsDto) => {
return await this.customerRepo.createOrUpdateContactList(contact, customerDto, contact._id);
}));
return Promise.all([updatedAddress, updatedContacts])

how to write findOneAndUpdate query in express.js?

i have shown my data , which is stored in database like this
{
"_id": {
"$oid": "5799995943d643600fabd6b7"
},
"Username": "xx",
"Email": "xx#gmail.com",
"Info": "Deactivate",
"Description": "aajdjdjddjdkjddjdjdhdj",
"VerificationCode": "594565",
"VerificationExpires": {
"$date": "2016-10-07T10:20:20.077Z"
}
}
My controller:
if Username, Email, Info are matched I need to update " Info = 'Active' " this is working at the same time i need to delete 'VerificationCode' field and 'VerificationExpires' field how can i achieve this?
exports.updatearticle = function(req, res) {
Article.findOneAndUpdate(
{ "Username":'xx', "Email":'xx#gmail.com', "Info": "Deactivate" },
{ "$set": { "Info": "Active" } },
{ "new": true }
function (err, doc) {
if (err) { // err: any errors that occurred
console.log(err);
} else { // doc: the document before updates are applied if `new: false`
console.log(doc); // , the document returned after updates if `new true`
console.log(doc.Info);
}
}
);
};
above condtion matched and info getting changed but i want to delete VerificationCode,VerificationExpires some one help me out
exports.updatearticle = function(req, res) {
Article.findOne( { "Username":'xx', "Email":'xx#gmail.com', "Info": "Deactivate" }, function(err, result){
if (!err && result) {
result.Info = "Active"; // update ur values goes here
result.VerificationCode = "";
result.VerificationExpires = {};
var article = new Article(result);
article.save(function(err, result2){
if(!err) {
res.send(result2);
} else res.send(err);
})
} else res.send(err);
});
}
home this may help

`mongolab` - getting error on post, not able to post a data

I have a account with mongolab(mlab). I am trying to post a data for the users using postman add-on from chrome browser. I am getting error always. I could not able to post a data. I have tried with other diffrent ways. but no luck.
any one help me to sort this issue?
here is my api.js :
var
User = require('../models/user'),
config = require('../../config'),
secretKey = config.secretKey;
module.exports = function( app, express ) {
var api = express.Router();
api.post('/signup', function (req, res) {
var user = new User({
name:req.body.name,
username:req.body.username,
password:req.body.password
});
user.save(function(err){
if(err){
res.send(err);
return;
}
res.json({message:'User has been Created!'});
});
});
api.get('/users', function(req, res) {
User.find({}, function( req, users){
if(err) {
res.send(err);
return;
}
res.json(users);
})
});
return api;
}
config.js :
module.exports = {
"database":"mongodb://xxx:xxxx#ds015700.mlab.com:15700/arifstory",
"port" : process.env.PORT || 3000,
"secretKey" : "YourSecretKey"
}
And the user.js :
var
mongoose = require('mongoose'),
Schema = mongoose.Schema,
bcrypt = require('bcrypt-nodejs');
var UserSchema = new Schema({
name : String,
userName:{ type:String, required:true, index : { unique: true }},
password : { type:String, required : true, select : false }
});
UserSchema.pre('save', function(next) {
var user = this;
if(!user.isModified('password')) return next();
bcrypt.hash( user.password, null, null, function(err, hash) {
if(err) return next(err);
user.password = hash;
next();
});
});
UserSchema.methods.comparePassword = function( password ) {
var user = this;
return bcrypt.compareSync(password, user.password);
}
module.exports = mongoose.model('User', UserSchema);
I really unable to understand the issue here. please any one help me?
error
{
"message": "User validation failed",
"name": "ValidationError",
"errors": {
"userName": {
"message": "Path `userName` is required.",
"name": "ValidatorError",
"properties": {
"type": "required",
"message": "Path `{PATH}` is required.",
"path": "userName"
},
"kind": "required",
"path": "userName"
},
"password": {
"message": "Path `password` is required.",
"name": "ValidatorError",
"properties": {
"type": "required",
"message": "Path `{PATH}` is required.",
"path": "password"
},
"kind": "required",
"path": "password"
}
}
}
The data sent from chrome could be undefined.
Print it in console by including the below 2 lines above user.save function in api.js file:
console.log(req.body.username);
console.log(req.body.password);
if it shows as undefined, then make sure to check "x-www-form-urlencoded" under "body" in Postman and provide username and password under that.