0

In my dialogflow fulfillment, I want to query a mongodb database and based on the result return an answer. Since I use the actions-on-google database, I must use promises for async calls. How can I do that for a mongodb query?

const express = require("express");
const bodyParser = require("body-parser");
const {dialogflow} = require('actions-on-google');
const app = dialogflow()
var MongoClient = require('mongodb').MongoClient;
var url = "mongodb://localhost:27017/"

app.intent('Mongodb', (conv) =>{
  MongoClient.connect(url, function(err, db) {
  if (err) throw err;
  var dbo = db.db("mydb");
  var query = { address: /^S/ };
  var path;

  db.collection('paths', function(err, collection) {
      collection.find({}).toArray(function(err, results) {
          path = results;
          console.log(results);
      });
  });
  });
  conv.ask(path)
});
Sairaj Sawant
  • 1,842
  • 1
  • 12
  • 16

1 Answers1

2

The Node mongodb package will return a Promise from most (maybe all?) of its callback-based APIs if you don't pass a callback function. For example, you can call db.collection('paths').then(function (collection) { … }). You can then chain the promises like the following:

return MongoClient.connect(url)
  .then(function (client) {
    return client.db('mydb');
  }).then(function (db) {
    return db.collection('paths');
  }).then(function (collection) {
    return collection.find({}).toArray();
  }).then(function (path) {
    conv.ask(path);
  });

You can also use the new Promise((resolve, reject) => …) constructor to wrap anything that is callback based in a Promise API. The Promise documentation on MDN has a good example here.

Tyler
  • 2,300
  • 1
  • 10
  • 9
  • Thank you very much! Shouldn't the last return be like this: return collection.find({}).toArray(path); – Simon Ravelingien Dec 27 '18 at 16:03
  • I don't think so... your code was previously assigning `paths = results`, where `results` is what `.toArray()` with no callback will return (wrapped in a Promise). By returning `.toArray()` the next `.then` will get the result as an argument, which is then passed to `conv.ask` on line 9 of the example. – Tyler Dec 27 '18 at 18:09
  • Your code worked, but I had to make a small edit. You need to put 'return' in front of MongoClient.connect otherwise Dialogflow gives this error message: "Error: No response has been set. Is this being used in an async call that was not returned as a promise to the intent handler?" – Simon Ravelingien Jan 01 '19 at 23:05