【问题标题】:Designing a questiion-and-answer system that is flexible and efficient设计灵活高效的问答系统
【发布时间】:2012-03-04 02:05:55
【问题描述】:

我一直在研究动态问答系统,但在为该系统创建高效且灵活的设计时遇到了麻烦。我很想知道是否有既定的设计模式或设计此系统的任何建议。

我想要做什么

我有一系列问题。回答完之后,会显示另一组问题,取决于前一组的答案。如此重复,直到不再需要问题为止。

问题答案都是布尔值、多项选择或数字。

重要的部分是大多数问题仅在满足一组特定条件时才会显示,基于之前的答案。
我需要的条件主要支持布尔逻辑,例如 And、Or、Not、Equals、Greater Than 和 Less Than。

例如,假设我已经收到AgeGenderState 等问题的答案。
下一个问题是In School?,但它应该只在以下情况下显示:Age < 30 AND Gender=Male AND (State = CA OR State = NY)

有没有人听说过类似的设计模式?您将如何处理这种设计?


背景资料

我试过数据库列

起初,我们只有 3 个初始问题,所以我们只使用 3 列来过滤第二组问题。

但是,我们的业务需求不断增长,我们开始需要更多初始问题、添加更多列并在这些过滤器中添加更多逻辑。

这很快就变得过于死板和繁琐。

我尝试了一个逻辑解释器

我们让系统更灵活的第二次尝试:将过滤逻辑存储为 JavaScript,并运行 JavaScript 解释器来过滤结果。

这在灵活性方面工作得很好,但是从数据库中检索数千行并解释脚本效率极低,而且对于生产来说性能太差。

我尝试了混合动力

我们最终将这两种方法结合起来,并提出了一些可行的方案。
我们首先根据几个硬编码的数据库列过滤我们的列表,然后使用 JavaScript 解释器进一步过滤列表。

这种混合系统仍然有很多缺点:

  • 逻辑在 2 个不同的系统中(SQL 数据库逻辑和 JavaScript 解释器)
  • 解释 JavaScript 速度很慢,而且对于所需的简单布尔逻辑来说可能是多余的
  • 该系统非常难以维护,尤其是因为 JavaScript 逻辑必须始终由开发人员编写。

我真的很想听听有关如何改进此设计的建议。

其他信息

我的数据库是 MS SQL Server,后端是 .NET C#,JavaScript 解释器是 JINT。 UI 实现并不重要,但它是一个支持 AJAX 的网站,用于提出和回答这些问题。

【问题讨论】:

  • 椰子,这是一个非常不寻常的反对理由。你喜欢回答只有一句话的问题吗?
  • 您是否考虑过NoSQL 数据库方法?比如MongoDB。?
  • @Coconut 我将实际问题移到顶部,并将其他所有内容标记为“背景信息”。希望这有助于简化阅读。
  • @Tigran 我们在系统的其他地方使用了MongoDB。如果非关系型数据库能提供好的解决方案,我全都听好了!
  • @ScottRippey 我有一些类似的要求,并尝试构建一个像你提到的那样的系统,你能否与我分享你的最终解决方案。我想知道设计。谢谢。

标签: c# sql design-patterns database-design


【解决方案1】:

过去我们不得不为医疗系统做类似的事情,由于其复杂性,我们不得不重用支持多分类决策树的规则引擎。我记得我遇到了一个很好的简单设计,并设法挖掘出链接。

http://www.javaworld.com/javaworld/javatips/jw-javatip139.html?page=1

该设计与数据存储松散耦合,因此可以轻松融入您现有的解决方案设计。

【讨论】:

  • 那是一篇很棒的文章,谢谢。当我想到我的要求时,我完全想到了报税软件。很高兴阅读其他人创建类似系统的经验。
  • 在这个例子中,我看到每个 answer 都有一个对应于另一个问题的 consequence。您认为我如何构建将特定组合答案与单个问题相关联的逻辑?
  • 如果这是一个交互式问卷,理论上当你遇到特定问题(结果)时,已经满足了许多先前的标准,例如 Q1 -> 答案 A,结果 Q3 -> 答案 B,结果 7 -> 答案 A,结果 Q8,因此 Q8 实际上是关联条件(答案的组合)的结果。如果您必须在分析中评估多个标准以得出答案,那么您应该考虑实施决策树算法
【解决方案2】:

如果我正确理解您的问题,听起来您正在构建finite state machine

每个状态对应一个问题,并根据您的答案转到一个新问题。同一个问题可能会出现在几个不同的州。

在您的示例中,开始状态将是问题“状态?”,如果答案是“CA”,我们将进入下一个状态,问题是“出租还是拥有?”。对于该问题的任何答案,下一个状态将是“年龄?”这个问题。因为“State?”->“Rent or Own?”没有进一步的子问题。路径。

对于您的数据库模型,您需要一个状态表和一个状态之间的关系表,即:

表格状态:

  • id (int)
  • 问题(varchar)
  • 类型(set[text, boolean, int])

表状态_状态:

  • fromState (int)
  • toState(int)
  • answerType (set[any, equals, greater, ...])
  • 回答(varchar)

在您的代码中,您只需要知道当前状态、提出问题、查询 state_state 并将结果与​​给出的答案进行比较,即可知道下一个状态的 id 是什么,从而知道下一个问题。

如果您有很多州都有相同的问题,您可以创建一个问题表并将其与州相关联。

如果您有多个“开始问题”,您可以拥有一个状态机并将结束问题与下一个“开始问题”联系起来,或者您可以拥有多个状态机。

【讨论】:

  • 在你编辑了你的问题后,我发现这可能不是你想要的。但是,如果您在问题已经回答的情况下自动更改状态,则无论如何您都可以使用该想法。这当然需要您将问题保存在单独的表格中。
  • 这是一种非常有趣的看待方式!
  • 我很难措辞这个问题......我首先写它的重点是问题路径,但经过一番思考,我意识到真正棘手的部分是条件标准逻辑。
【解决方案3】:

我们有类似的要求来创建自定义调查。我们有 3 个表,问题、响应和问题路由。响应表允许您为每个问题创建多个答案,并且 questionroute 表允许您根据特定响应选择下一个问题。

CREATE TABLE [dbo].[Question]
(
QuestionID uniqueidentifier,
[Text] varchar(512)
)
CREATE TABLE [dbo].[Response]
(
ResponseID uniqueidentifier,
QuestionID uniqueidentifier,
[Text] varchar(512)
)
CREATE TABLE [dbo].[QuestionRoute]
(
QuestionRouteID uniqueidentifier,
QuestionID uniqueidentifier,
ResponseID uniqueidentifier,
NextQuestionID uniqueidentifier
)

【讨论】:

  • 问题是“显示另一组问题,具体取决于前一组的答案”。您的解决方案非常适合一次导航一个问题,但很难应用于一组问题。此外,这不支持整个布尔逻辑。
  • 你说得对,我错过了一次提出的 3 个问题。我想你可以为“QuestionSet”添加另一个表,但是布尔值仍然丢失...... :)
  • 感谢您的贡献。布尔值是问题的重要组成部分,但我很高兴知道其他人如何解决类似问题!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-10-11
  • 1970-01-01
  • 1970-01-01
  • 2022-08-04
  • 2015-12-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多