Мой бот Dialogflow + Firebase не извлекает данные из Bigquery - PullRequest
0 голосов
/ 08 января 2020

Я построил бота в диалоговом потоке и следовал указаниям по его интеграции с базой данных BigQuery, описанным в Деконструкция чат-ботов , Документация BigQuery по параметризованным запросам с Node.JS и Чат службы поддержки с BigQuery

Вызов BigQuery осуществляется в рамках асинхронной c функции ' queryParamsArrays () ', которая, по-видимому, является проблемой, основанной на журналах Firebase. ,

Я обновил пакет. json, указав "engine: 8" и / * jshint esversion: 8 * / в файле индекса, чтобы переопределить ошибку. Отходя от документации BigQuery, я подумал, что это может сработать. Желаемое поведение состоит в том, что список вин извлекается из базы данных и представляется случайным образом конечному пользователю. Вместо этого я вижу сгенерированный текст запроса SQL, и функция list_wines (которая вызывает asyn c) завершается без подстановки каких-либо значений в.

Я собираюсь попробовать переписать asyn c как обещание функция. Может кто-нибудь сказать мне, если я на правильном пути? Я новичок в javascript и пытаюсь пройти через него sh.

index. js

     // See https://github.com/dialogflow/dialogflow-fulfillment-nodejs
     // for Dialogflow fulfillment library docs, samples, and to report issues
    'use strict';

    /* jshint esversion: 8 */


    const functions = require('firebase-functions');
    const {WebhookClient} = require('dialogflow-fulfillment');
    const {Card, Suggestion} = require('dialogflow-fulfillment');
    const {google} = require('googleapis');
    const BIGQUERY = require('@google-cloud/bigquery');

    process.env.DEBUG = 'dialogflow:debug'; // enables lib debugging statements

    exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => {
      const agent = new WebhookClient({ request, response });
      console.log('Dialogflow Request headers: ' + JSON.stringify(request.headers));
      console.log('Dialogflow Request body: ' + JSON.stringify(request.body));
      console.log("Parameters", agent.parameters);

      function getPair(agent) {
        // Return wines that pair well with the food or meet other user specified params

        const results= list_wines(agent);
        agent.add('${results[0].name} is a good choice for ${results[0].food_pairing}. A ${results[1].variety} like ${results[1].name} also works!');
      }

      // Run the proper function handler based on the matched Dialogflow intent name
        let intentMap = new Map();
        intentMap.set('findPair', getPair);
        agent.handleRequest(intentMap);
    });

    function list_wines(agent) {
      // Search the database for parameters 
      // Actual values have been removed for presentation

      const projectId = 'my_project_id';
      const datasetId = "my_dataset_id";
      const tableId = "my_table_id";

      const bigquery = new BIGQUERY({
        projectId: projectId
      });

      const params= agent.parameters;
      const excluded= agent.excluded;

      const name = agent.parameters.label;
      const variety = agent.parameters.variety;
      const food_pairing = agent.parameters.foods;
      const conditions = agent.parameters.conditions;

      // Map param columns to those in the BigQuery database
      const SQL_COLUMN_LABELS={label:'name', variety:'variety', foods:'food_pairing', conditions:'food_pairing'};

      var txt = "SELECT *, RANK() OVER(PARTITION BY food_pairing ORDER BY variety) as cat_count FROM \'my_project_id.my_dataset_id.my_table_id\'";

      var x;
      var filters=[];

      // Loop through params to add search params to the SQL query removing blank arrays and empty text
      // Also handles arrays with a single value or multiple values

      for (x in params) {
        // Correctly checking for Array
        if(!Array.isArray(params[x]) & params[x].length>1 ){
          // If the value is text we can reference it in the query with @
          filters = filters.concat(SQL_COLUMN_LABELS[x] + "= @" + x);
        } else{
          switch(params[x].length) {
              default:
                // Array with more than one value
                filters=filters.concat(SQL_COLUMN_LABELS[x] + " IN UNNEST(@" + x +")");
                break;
              case 1:
                // Array with one value - get the actual value
                filters = filters.concat(SQL_COLUMN_LABELS[x] + "= '" + params[x] +"'");
                break;
              case 0:
                // Empty Array
                break;
          } 
        }
      }

      txt += " WHERE " + filters.join(" AND ");

      // Prints output(the SQL query) to console
      console.log(txt);

      // This async function is supposed to query the database but it doesn't get called. 
      // list_wines completes and returns text without results

      async function queryParamsArrays() {

        console.log('calling queryParamsArrays');

        const sqlQuery = txt +';';

        console.log("SQL Query", sqlQuery);

        const options = {
          query: sqlQuery,
          // Location must match that of the dataset(s) referenced in the query.
          location: 'US',
          params: params,
                };
        try{
           // Run the query returning an array of objects
            const [rows] = await bigquery.query(options);

            console.log('Rows:');
            rows.forEach(row => {
              console.log(row)
            });


            // Pick ten results at random by shuffling rows
            const shuffled = rows.sort(() => 0.5 - Math.random());

            // Get sub-array of first 10 elements after shuffled
            let selected = shuffled.slice(0, 10);

            // Return selected 
            return selected;

        } catch(e) {
          console.log(e);
        }
      }
    }

package. json

    {
      "name": "dialogflowFirebaseFulfillment",
      "description": "This is the default fulfillment for a Dialogflow agents using Cloud Functions for Firebase",
      "version": "0.0.1",
      "private": true,
      "license": "Apache Version 2.0",
      "author": "Google Inc.",
      "engines": {
        "node": "8"
      },
      "scripts": {
        "start": "firebase serve --only functions:dialogflowFirebaseFulfillment",
        "deploy": "firebase deploy --only functions:dialogflowFirebaseFulfillment"
      },
      "dependencies": {
        "actions-on-google": "^2.2.0",
        "firebase-admin": "^5.13.1",
        "firebase-functions": "^2.0.2",
        "dialogflow": "^0.6.0",
        "dialogflow-fulfillment": "^0.5.0",
        "@google-cloud/bigquery": "^0.12.0"
      }
    }              

1 Ответ

0 голосов
/ 24 января 2020

Я исправил эту проблему. Вот где я ошибся:

  1. return queryParamsArrays (); внутри функции list_wines. Я забыл решающий шаг, который был ошибкой ладьи ie. Вы можете поместить это в код после завершения функции asyn c
  2. . Вы не можете передавать параметры, поскольку DialogFlow предоставляет их параметрам, как определено в параметрах. Вы должны очистить это, поскольку DF не делает достаточно хорошую работу
  3. строковых литералов - я не заметил, что код, который я заимствовал из использованных обратных кавычек вместо одиночных кавычек. Это исправило проблемы, когда коды должны были заменять части строки результатами запроса.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...