node.js - 如何使用 NodeJs 和 Mongoose 在 Bot Framework 中本地使用 MongoDB 和 directline-js 进行状态管理?

标签 node.js mongodb mongoose botframework direct-line-botframework

我正在本地 MongoDB 存储中维护机器人状态。当我尝试使用 directline-js 将对话移交代理时,它显示错误 BotFrameworkAdapter.sendActivity(): Missing Conversation ID。对话 ID 正在保存在 MongoDB 中

当我将中间层从Array更改为MongoDB时,出现了问题。我已经使用带有数组和默认内存存储的 directline-js 成功实现了相同的机器人与人类的交接。

BotFramework 中的内存存储

const { BotFrameworkAdapter, MemoryStorage, ConversationState, UserState } = require('botbuilder')
const memoryStorage = new MemoryStorage();
conversationState = new ConversationState(memoryStorage);
userState = new UserState(memoryStorage);

用于移交代理的中间层

case '#connect':
  const user = await this.provider.connectToAgent(conversationReference);
  if (user) {
             await turnContext.sendActivity(`You are connected to 
${ user.userReference.user.name }\n ${ JSON.stringify(user.messages) }`);

   await this.adapter.continueConversation(user.userReference, async 
   (userContext) => {
         await userContext.sendActivity('You are now connected to an agent!');
                    });
                    } 
   else {
 await turnContext.sendActivity('There are no users in the Queue right now.');
         }

使用 MongoDB 时,this.adapter.continueConversation 会引发错误。 使用数组时,它工作得很好。 MongoDB 和 Array 对象在结构上都很相似。

最佳答案

由于这适用于 MemoryStorage 而不是您的 MongoDB 实现,我猜测您的 MongoDB 实现有问题。本次回答将重点围绕这一点。如果不是这种情况,请提供您的 MongoDb 实现和/或您的存储库的链接,我可以解决这个问题。

<小时/>

仅当您想使用自定义模型/类型/接口(interface)时才需要 Mongoose。对于实现 BotState 的存储,你只需要写一个自定义的 Storage适配器。

基本知识 are documented here 。虽然是为 C# 编写的,但您仍然可以将这些概念应用到 Node。

1。安装mongodb

npm i -S mongodb

2。创建一个 MongoDbStorage 类文件

MongoDbStorage.js

var MongoClient = require('mongodb').MongoClient;

module.exports = class MongoDbStorage {
    constructor(connectionUrl, db, collection) {
        this.url = connectionUrl;
        this.db = db;
        this.collection = collection;

        this.mongoOptions = {
            useNewUrlParser: true,
            useUnifiedTopology: true
        };
    }

    async read(keys) {
        const client = await this.getClient();
        try {
            var col = await this.getCollection(client);

            const data = {};
            await Promise.all(keys.map(async (key) => {
                const doc = await col.findOne({ _id: key });
                data[key] = doc ? doc.document : null;
            }));
            return data;
        } finally {
            client.close();
        }
    }

    async write(changes) {
        const client = await this.getClient();
        try {
            var col = await this.getCollection(client);

            await Promise.all(Object.keys(changes).map((key) => {
                const changesCopy = { ...changes[key] };
                const documentChange = {
                    _id: key,
                    document: changesCopy
                };
                const eTag = changes[key].eTag;

                if (!eTag || eTag === '*') {
                    col.updateOne({ _id: key }, { $set: { ...documentChange } }, { upsert: true });
                } else if (eTag.length > 0) {
                    col.replaceOne({ _id: eTag }, documentChange);
                } else {
                    throw new Error('eTag empty');
                }
            }));
        } finally {
            client.close();
        }
    }

    async delete(keys) {
        const client = await this.getClient();
        try {
            var col = await this.getCollection(client);

            await Promise.all(Object.keys(keys).map((key) => {
                col.deleteOne({ _id: key });
            }));
        } finally {
            client.close();
        }
    }

    async getClient() {
        const client = await MongoClient.connect(this.url, this.mongoOptions)
            .catch(err => { throw err; });

        if (!client) throw new Error('Unable to create MongoDB client');

        return client;
    }

    async getCollection(client) {
        return client.db(this.db).collection(this.collection);
    }
};

注意:我只对此做了一些测试 - 足以让它与 the Multi-Turn-Prompt Sample 很好地配合工作。 。使用风险由您自行承担,并根据需要进行修改。

我基于这三种存储实现的组合:

3。在您的机器人中使用它

index.js

const MongoDbStorage = require('./MongoDbStorage');

const mongoDbStorage = new MongoDbStorage('mongodb://localhost:27017/', 'testDatabase', 'testCollection');

const conversationState = new ConversationState(mongoDbStorage);
const userState = new UserState(mongoDbStorage);

关于node.js - 如何使用 NodeJs 和 Mongoose 在 Bot Framework 中本地使用 MongoDB 和 directline-js 进行状态管理?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57639411/

相关文章:

node.js - 更新 Mongoose 中符合条件的数组

node.js - 通过 mongodb 保存表单部分

node.js - 和内部条件或条件 Mongoose

node.js - 带项目和过滤器的 Mongoose 查询

node.js - 启动 N|Solid Proxy 时出现 'Could not find configuration for port' 错误

javascript - 如何从textarea ejs文件中获取数据库的数组?

javascript - Knex 迁移播种完成但出现外键错误

angularjs - 为 MEAN.JS 文章添加评论

android - 如何将外部 npm 包添加到 phonegap?

node.js - Node JS 广播(音频流)