如何将会话数据存储到bot构建器中的自定义存储中

时间:2017-04-01 06:58:15

标签: node.js botframework

我正在使用节点js来构建聊天机器人。

我目前正在将会话数据存储到Microsoft默认存储中,每个用户会话的限制为64K。我想使用自己的存储来存储会话数据。 Here是我从Microsoft开发人员那里得到的帮助。

我可以存储在文档DB和Azure表中。

不过,我很困惑。我们如何实现IStorageClient接口存储在自己的数据库中?

每当我设置session.UserData.name=""时,它应该存储在自己的数据库中。

4 个答案:

答案 0 :(得分:3)

我不确定我是否得到了这个问题;我明白你要做的是什么,似乎你已经完成了所有的工作。

首先,您必须实现IStorageClient接口。在您的实现中,您编写逻辑以在数据库中存储内容。

您可以查看DocumentDBAzure Tables实施,以了解如何实施。

现在,问题是..如果您的自定义存储位于Azure ...中,那么您可以将AzureBotStorage与自定义存储客户端一起使用。您实例化自定义存储客户端,传递对AzureBotStorage的引用并将其设置为bot中的存储

// Azure DocumentDb State Store
var docDbClient = new azure.DocumentDbClient({
    host: process.env.DOCUMENT_DB_HOST,
    masterKey: process.env.DOCUMENT_DB_MASTER_KEY,
    database: process.env.DOCUMENT_DB_DATABASE,
    collection: process.env.DOCUMENT_DB_COLLECTION
});
var botStorage = new azure.AzureBotStorage({ gzipData: false }, docDbClient);

// Set Custom Store
bot.set('storage', botStorage);

如果您的自定义存储位于Azure之外的任何其他位置,则AzureBotStorage可能不适合您。请注意,我不确定这一点,您必须检查代码以确认。从我看到的,它看起来非常通用,因此您可以重用它并只实现IStorageClient。如果不是这样,您还必须实现IBotStorage接口。

最后,AzureBotStorage正在这样做。它实现IBotStorage并使用IStorageClient与实际提供者进行交互。

答案 1 :(得分:2)

我编写代码将bot数据存储到Mongo Db中。 完整的代码和详细信息可以在BotBuilder-MongoDB

中找到

IstorageClient 接口实现代码:

"use strict";
var Consts = require('./Consts');
var mongodb_1 = require("mongodb");
var replaceDot_Atrate = require("./replaceDot");
var mongoDbConnection = require('./connection.js');
var conf = require('../config');
var conversational_collname = conf.db.conversationalCollection;

var IStorageClient = (function () {

    function IStorageClient(options) {
        this.options = options;
    }

    IStorageClient.prototype.retrieve = function (partitionKey, rowKey, callback) {
        var id = partitionKey + ',' + rowKey;
        if(rowKey!=="userData"){
            var query={"$and":[{"userid":id}]}
                mongoDbConnection(function(err,db) {
                var iterator= db.collection(conversational_collname).find(query);
                iterator.toArray(function (error, result, responseHeaders) {
                    if (error) {
                        console.log("Error",error)
                        callback(error, null, null);
                    }
                    else if (result.length == 0) {
                        callback(null, null, null);
                    }
                    else {
                        var document_1 = result[0];
                        var finaldoc=replaceDot_Atrate.substituteKeyDeep(document_1, /\@/g, '.');
                        finaldoc["id"]=id
                        callback(null, finaldoc, null);
                    }
                });
            }); 
        }
        else{
            var query={"$and":[{"userid":partitionKey}]}
            mongoDbConnection(function(err,db) { 

                var iterator= db.collection(conversational_collname).find(query);
                iterator.toArray(function (error, result, responseHeaders) {
                    if (error) {
                        callback(error, null, null);
                    }
                    else if (result.length == 0) {
                        //console.log("result length 0")
                        callback(null, null, null);
                    }
                    else {
                        var document_1 = result[0];
                        callback(null, document_1, null);
                    }
                });
            });
        }
    };

    IStorageClient.prototype.initialize = function (callback) {
        var _this = this;
        var client=mongodb_1.MongoClient;
        this.client = client;

        mongoDbConnection(function(err,database) {    
                _this.database = database;
                _this.collection = database.collection(conversational_collname);
                callback(null);
         });
    };

    IStorageClient.prototype.insertOrReplace = function (partitionKey, rowKey, entity, isCompressed, callback) {
        var id=partitionKey + ',' + rowKey
        var docDbEntity = { id: partitionKey + ',' + rowKey, data: entity, isCompressed: isCompressed };
        if(rowKey!=="userData"){
            var newEntitiy=replaceDot_Atrate.substituteKeyDeep(entity, /\./g, '@');
            var conditions1 = {
                'userid': id
            };
            var updateobj1 = {
                "$set": {"data":newEntitiy,"isCompressed":false}
            };   
            mongoDbConnection(function(error,db) {    
                db.collection(conversational_collname).update(conditions1,updateobj1,{upsert: true},function(err,res){
                callback(error, null,"");
            });
            });
        }
        else{
            var conditions = {
                'userid': partitionKey
            };
            var update = {
                "$set": {"data":entity}
            }
            mongoDbConnection(function(error,db) {    
                db.collection(conversational_collname).update(conditions,update,{upsert: true},function(err,res){
                callback(error, null,"");
           })
        });
        } 
    };


    IStorageClient.getError = function (error) {
        if (!error)
            return null;
        return new Error('Error Code: ' + error.code + ' Error Body: ' + error.body);
    };

    return IStorageClient;
}());
exports.IStorageClient = IStorageClient;

答案 2 :(得分:1)

这是对此库的另一种看法:mongo-bot-storage

import {MongoDbBotStorage, MongoDBStorageClient} from "mongo-bot-storage";

// use it like this 
bot.set("storage", new MongoDbBotStorage(new MongoDBStorageClient({
    url: "mongodb://localhost/mydb",
    mongoOptions: {}
})));

// or like this
MongoClient.connect("mongodb://localhost/mydb", (error, db) => {
    bot.set("storage", new MongoDbBotStorage(new MongoDBStorageClient({db})));
});

然后使用默认的session.userData等等。

别忘了

// Enable Conversation Data persistence
bot.set('persistConversationData', true);

答案 3 :(得分:1)

我将这个答案发布在一个非常老的线程上,只是因为它似乎是实现Bot Framework自定义存储选项的最佳结果。

有一个非常简单的解决方案,它不涉及使用一段时间内未更新的npm,这会带来无法在公司环境中进行审核的风险,或者会使控制台中充满大量日志条目。

最简单的方法是按照Undocumented Guide for Custom Data Storage in Microsoft Bot Framework

中的步骤,使用最新的数据库驱动程序为您的机器人创建自己的数据存储代码。

我花了一个小时左右的时间来实现MongoDB,其中包括一些针对最新驱动程序的学习曲线。

简而言之,万一链接消失了,您可以创建一个中间件,该中间件导出Bot Framework正在寻找的两个关键功能:getDatasaveData。每一个都必须具有以下粗略结构(来自使用Redis的链接):

var storageKey = 'conversationId';
module.exports = {
getData : (data, callback) => {
    redisClient.get(data[storageKey], (err, reply) => {
        if (err || !reply) {
            callback(err, null);
        } else {
            callback(null, JSON.parse(reply));
        }
    })
},
saveData : (data, value, callback) => {
        redisClient.set(data[storageKey], JSON.stringify(value), (err, reply) => {
            if (err) {
                callback(err);
            } else if (reply === 'OK') {
                callback(null);
            }
        })
    }
}

然后,请确保在app.js中使用require()中间件并进行相应设置:

const dbMiddleware = require('./path/to/middleware')

bot.set('storage', dbMiddleware)