如何在本地使用 MongoDB 和 directline-js 在使用 NodeJs 和 Mongoose 的 Bot Framework 中进行状态管理?
How to use MongoDB locally and directline-js for state management in Bot Framework using NodeJs and Mongoose?
我在 本地 MongoDB 存储中维护 bot 状态。当我尝试使用 directline-js 将对话 移交 给 agent 时,它显示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.');
}
this.adapter.continueConversation
在使用 MongoDB 时抛出错误。
在使用 Array 时,它可以正常工作 。 MongoDB 和 Array 对象在结构上都相似。
由于这适用于 MemoryStorage 而不是您的 MongoDB 实施,我猜您的 MongoDB 实施有问题。这个答案将集中于此。如果不是这种情况,请向您的存储库提供您的 MongoDb 实现 and/or 和 link,我可以解决这个问题。
仅当您想使用自定义 models/types/interfaces 时才需要 Mongoose。对于实现 BotState
, you just need to write a custom Storage 适配器的存储。
are documented here 的基础知识。虽然是为 C# 编写的,但您仍然可以将这些概念应用于 Node。
1。安装 mongodb
npm i -S mongodb
2。创建 MongoDbStorage
class 文件
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);
我在 本地 MongoDB 存储中维护 bot 状态。当我尝试使用 directline-js 将对话 移交 给 agent 时,它显示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.');
}
this.adapter.continueConversation
在使用 MongoDB 时抛出错误。
在使用 Array 时,它可以正常工作 。 MongoDB 和 Array 对象在结构上都相似。
由于这适用于 MemoryStorage 而不是您的 MongoDB 实施,我猜您的 MongoDB 实施有问题。这个答案将集中于此。如果不是这种情况,请向您的存储库提供您的 MongoDb 实现 and/or 和 link,我可以解决这个问题。
仅当您想使用自定义 models/types/interfaces 时才需要 Mongoose。对于实现 BotState
, you just need to write a custom Storage 适配器的存储。
are documented here 的基础知识。虽然是为 C# 编写的,但您仍然可以将这些概念应用于 Node。
1。安装 mongodb
npm i -S mongodb
2。创建 MongoDbStorage
class 文件
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);