I am having trouble reading a FireStore document file through DialoFlow ES - google-cloud-firestore

We are trying to read a document file from Firestore through Dialogflow. We get as far as "I can't find your reservation." Each document's id is auto generated, so we can't match from the Document ID field (or at least do not know how to). Any help would be greatly appreciated!
Fulfillment function code:
function readReservation(agent) {
let id = agent.parameters.name.toString();
let collectionRef = db.collection('reservations');
let userDoc = collectionRef.doc(id);
return userDoc.get()
.then(doc => {
if (!doc.exists) {
agent.add('I could not find your reservation.');
} else {
db.collection('reservations').doc(id).update({
newname: agent.parameters.newname
}).catch(error => {
console.log('Transaction failure:', error);
return Promise.reject();
});
agent.add('Ok. I have updated the name on the reservation.');
}
return Promise.resolve();
}).catch(() => {
agent.add('Error reading entry from the Firestore database.');
});
}
I have tried different ways to write this code, but was unsuccessful.

Related

Having trouble saving document to mongoDB

so I'm having a really hard time getting the document to save to the database in the case where the product already exists in the cart. I am able to target the item from the database, make changes to it and console output the correct values but in this particular case it wont save the result to the Database. I've tried rewriting it using the updateOne() function and I had little luck. I could really use the help i'm super stuck on this probem. Pics for more info: Block of code that's not working, console output that reflects desired change, mongoDB document that the changes will not save to.
If anyone could point me in the right direction I would greatly appreciate it.
router.post('/add-to-cart',[
auth,
check('productId','productId is required').not().isEmpty(),
check('quantity', 'quantity is required').not().isEmpty()
] , async (req,res) => {
//checks field validation
const errors = validationResult(req);
if(!errors.isEmpty()){
res.status(400).json({errors:errors.array()});
};
//Takes token from the header
const token = req.header('x-auth-token');
if (!token){
return res.status(401).json({ msg: 'no token, auth denied'});
}
//decode token and find associated user
const decoded = jwt.verify(token, config.get('jwtSecret'));
let userPayload = decoded.user;
//build cart object
try{
//populate from request body
const {productId, quantity} = req.body;
//find User using the payload
let user = await User.findById(userPayload.id);
//get the product from db
let product = await Product.findById(productId);
//calculate price of item(s) added to cart
let total = ( quantity * product.price);
//create cart object
//Check to see if cart already exists
let iscart = await Cart.findOne({user:user});
//there is an existing cart
*if(iscart){
let found = false;
for (i=0;i<iscart.orderItems.length;i++)
{
if(iscart.orderItems[i].product._id.toString() == product._id.toString()){
found=true;
console.log('found that product!');
iscart.orderItems[i].qty += quantity;
try{
await iscart.save();
console.log(iscart);
}
catch(err){
console.error(err);
res.status(500).send('server error');
}
res.status(200).send(iscart.orderItems[i]);
break;
}*
}
if(!found){
await Cart.updateOne(
{user:iscart.user},
{$push:{orderItems:
{
product:product,
qty:quantity,
total:total
}}
}
)
res.status(200).send('product pushed to orderItems')
}
}
//there isnt an existing cart so we create one
else{
const cart = new Cart({
user,
orderItems:
{ product:product,
qty:quantity,
total:total
}
})
await cart.save();
res.status(200).send('cart created and saved');
}
}
catch(err){
console.error(err);
res.status(500).send('server error');
}
})
Figured it out!! When you are updating a nested object inside of a document you have to mark the object as modified so it knows to update it. this line fixed my issue:
iscart.markModified('orderItems');

How to check if value already exists in the data received from api before inserting it into db

I am having hard times trying to write data received from a api to db.
I successfully got data and then have to write it to db. The point is to check whether the quote is already exists in my collection.
The problem I am dealing with is that every value gets inserted in my collection, not regarding if it exists or not.
const { MongoClient } = require('mongodb')
const mongoUrl = 'mongodb://localhost/kanye_quotes'
async function connectToDb() {
const client = new MongoClient(mongoUrl, { useNewUrlParser: true })
await client.connect()
db = client.db()
}
async function addQuote(data) {
await connectToDb()
try {
const collection = db.collection('quotes')
let quotes = [];
quotes = await collection.find({}).toArray()
if (quotes = []) { // I added this piece of code because if not check for [], no values will be inserted
collection.insertOne(data, (err, result) => {
if (err) {
return
}
console.log(result.insertedId);
return
})
}
quotes.forEach(quote => {
if (quote.quote !== data.quote) { // I compare received data with data in collection, it actually works fine(the comparison works as it supposed to)
collection.insertOne(data, (err, result) => {
if (err) {
return
}
console.log(result.insertedId);
})
} else console.log('repeated value found'); // repeated value gets inserted. Why?
})
}
catch (err) {
console.log(err)
}
}
Hi it's probably better to set unique: true indexing on your schema. That way you won't have duplicated values.

How to retrieve currentUser data with Vue.js, AWS Amplify, and MongoDB

I am attempting to build a Vue.js App that synthesizes properties of AWS, MongoDB, and Express. I built an authentication page for the app using aws-amplify and aws-amplify-vue. After logging into the app, metadata containing the username for the logged in AWS user is passed into data object property this.name like so:
async beforeCreate() {
let name = await Auth.currentAuthenticatedUser()
this.name = name.username
}
this.name is then added to MongoDB via Axios:
async addName() {
let uri = 'http://localhost:4000/messages/add';
await this.axios.post(uri, {
name: this.name,
})
this.getMessage()
}
I also have a getName() method that I am using to retrieve that data from MongoDB:
async getData () {
let uri = 'http://localhost:4000/messages';
this.axios.get(uri).then(response => {
this.userData = response.data;
});
},
This method, however, returns data for ALL users. I want to reconfigure this method to ONLY return data for .currentAuthenticatedUser(). In my previous experience with Firebase, I would set up my .getData() method with something like:
let ref = db.collection('users')
let snapshot = await ref.where('user_id', '==', firebase.auth().currentUser.uid).get()
...in order to return currentUser information on the condition that 'user_id' in the collection matches the currently logged-in Firebase user.
To achieve this with MongoDB, I attempted to configure the above method like so:
async getData () {
let uri = 'http://localhost:4000/messages';
let snapshot = await uri.where('name', '==', this.name);
this.axios.get(snapshot).then(response => {
this.userData = response.data;
});
},
My thought here was to try and return current user data by comparing 'name' in the MongoDB collection with the logged-in user stored in this.name...but I understand that this might not work because the .where() method is probably unique to Firebase. Any recommendations on how to configure this .getData() to return ONLY data associated with the currentAuthenticatedUser? Thanks!
EXPRESS ROUTES:
const express = require('express');
const postRoutes = express.Router();
// Require Post model in our routes module
let Post = require('./post.model');
// Defined store route
postRoutes.route('/add').post(function (req, res) {
let post = new Post(req.body);
post.save()
.then(() => {
res.status(200).json({'business': 'business in added successfully'});
})
.catch(() => {
res.status(400).send("unable to save to database");
});
});
// Defined get data(index or listing) route
postRoutes.route('/').get(function (req, res) {
Post.find(function(err, posts){
if(err){
res.json(err);
}
else {
res.json(posts);
}
});
});
module.exports = postRoutes;
It is not possible to apply a where clause to a uri AFAIK. What you should do is adding a where clause to the actual query you are making in your backend and, to do that, send the username you want to filter the query with through a query parameter like this: /messages?name=JohnDoe.
So basically if you are using a Node/Express backend, as you suggested, and using Mongoose as the ODM for MongoDB your request would probably be looking something like this:
const Users = require('../models/users.model');
Users.find({}, function (e, users) {
if (e) {
return res.status(500).json({
'error': e
})
}
res.status(200).json({
'data': users
});
})
What you should do is getting the username query parameter through req.query and add it to the options in the first parameter of the find function.
const Users = require('../models/users.model');
let params = {},
name = req.query.name;
if (name) {
params.name = name
}
Users.find(params, function (e, users) {
if (e) {
return res.status(500).json({
'error': e
})
}
res.status(200).json({
'data': users.slice
});
})
That way if you point to /messages?name=John you will get the users with "John" as their name.
Edit:
If your backend is configured in the following way
postRoutes.route('/').get(function (req, res) {
Post.find(function(err, posts){
if(err){
res.json(err);
}
else {
res.json(posts);
}
});
});
what you should do is get the query parameters from inside the get method
postRoutes.route('/').get(function (req, res) {
let params = {},
name = req.query.name
if (name) {
params.name = name
}
Post.find(params, function(err, posts){
if(err){
res.json(err);
}
else {
res.json(posts);
}
});
});

Mongoose cannot findOne({_id : id}) with copied documents

I copied documents from a local database to my production database and when I try to get the document by Id by running model.findOne({_id : id}) and mongoose returns nothing. I am copying the documents over with the same Id, but I also tried with a new Id. I can find the document in the database and confirm that the JSON is correct, the Id is correct, etc and it won't find it. The documents I did not copy and where generated via my app still query fine with the findOne command. So, I have no idea what's going on
any help is greatly appreciated, thanks
groups.crud
getGroupById(id: string) {
logger.debug(".getGroupById id: " + id);
return new Promise(function(resolve, reject) {
GroupsModel.findById(id)
.populate('createdBy')
.then(function (group) {
logger.debug(".getGroupById");
if(group.createdBy.privacySettings.useUserName) {
group.createdBy.firstName = '';
group.createdBy.lastName = '';
}
resolve(group);
})
.catch(function(error) {
reject(error);
});
});
}
groups.routes
getGroupById(req, res, next) {
logger.debug('.getGroupById: BEG');
let id = req.params.id;
return groupsCrud.getGroupById(id)
.then(function(group) {
if(group) {
logger.debug('.getGroupById: get by id success');
let response = {
data : group
}
logger.debug('.getGroupById: response: ' + response);
res.json(response);
}
else {
logger.debug('.getGroupById: get by id failed 1');
res.status(404).json({ status : 404, message : "Group not found."});
}
})
.catch(function(error) {
logger.debug('.getGroupById: get by id failed 2 err = ' + JSON.stringify(error, null, 2));
res.sendStatus(404);
});
}

Issue with getting information from mongodb

Ok so here is what I am trying to do, I have a Item collection that holds a users items along with price quantity and description. I have also created a collection called soldItems that will store information about a sold item once the user inputs the required data and submits the form. I am not sure if I am doing this correctly to begin with and I have been trying to research this but I don't exactly know what I am looking for.
Here is the code I have so far
router.post("/item/:id", middleware.isLoggedIn, (req, res) => {
Item.findById(req.params.id, (err, item) => {
if(err) {
console.log(err);
}
var soldItem = {
id: req.params.id,
item: req.item.name,
askPrice: req.item.price
};
var soldPrice = req.body.soldPrice;
var soldQuantity = req.body.soldQuantity;
var itemSold = {
soldItem: soldItem,
soldPrice: soldPrice,
soldQuantity: soldQuantity
};
SoldItem.create(itemSold, (err, newlyCreated) => {
if (err) {
console.log(err);
} else {
item.soldItems.push(newlyCreated);
item.save();
req.flash("success", "Item Sold");
res.redirect("back");
}
});
});
});
So... Item.findById(req.params.id) works because I am pulling the ObjectId from the url. However, how would I be able to use req.item._id. Because the issue I am having is when I am trying to get req.item.name and req.item.price I am being told that it cannot read property 'name' or 'price' of undefined. How can I get that information?