php - Sphinx搜索的数据库定义

标签 php mysql sql search sphinx

背景

我正在创建一个MySQL数据库来存储诸如课程之类的项目,其中单个课程可能具有许多属性。例如:

一门课程可能具有以下任何或所有属性:


标题(varchar)
次要标题(varchar)
说明(文字)
日期
时间
具体位置(varchar;例如,白厅7号厅)
一般位置(varchar;例如内华达州拉斯维加斯)
位置坐标(浮动;例如lat,long)
等等


数据库设置如下:

一张存储特定课程信息的表:

课程表:


Course_ID(每个课程的主键唯一ID)
Creator_ID(创建者的唯一ID)
Creation_Date(课程创建的日期)
Modified_Date(这是修改课程的最新时间戳记)


存储每个课程的多个属性的表设置如下:

course_attributes表:


Attribute_ID(每个属性的唯一ID)
Course_ID(针对特定课程属性的引用)
属性(varchar定义属性;例如“ title”)
值(包含指定属性值的文本;例如,“我的课程标题”)


欲望

我想使用狮身人面像搜索来搜索该数据库。通过此搜索,我在不同的字段中权衡了不同的金额,例如:“标题”比“描述”更重要。

我希望具有的特定搜索字段是:


标题
日期
位置(字符串)
位置(地理位置-纬度/经度)


问题

我应该在Mysql中定义一个视图以根据“标题”,“描述”等组织属性,还是可以通过一种方法定义sphinx.conf文件来理解特定属性?

我愿意接受所有解决此问题的建议,无论是数据库/表的重新排列还是搜索的方式。

让我知道您是否需要其他详细信息来帮助我找到解决方案。

先谢谢您的帮助

!-更新-!

好的,因此在阅读了一些答案之后,我觉得我应该提供一些附加信息。

纬度/经度

纬度/经度属性是我在接收到常规位置字符串后在内部创建的。我可以用任何希望的方式生成值,这意味着我可以将它们一起存储在一个lat / long属性中,作为“ float lat,float long”值或任何其他所需格式。仅在从初始位置字符串生成并验证它们之后才执行此操作。这是为了防止格式错误的数据,如@ X-Zero和@Cody所建议的。

请记住,纬度和经度仅说明需要对该字段进行搜索,而不是除此以外的任何内容。这仅仅是另一个属性;其中之一。

加权搜索结果

我知道如何在Sphinx搜索查询中为结果添加权重:

$cl->setFieldWeights( array('title'=>1000, 'description'=>500) );


如果结构是@ X-Zero建议的,这将导致title列的权重高于description列。我的问题更针对如何将上述逻辑应用于当前表定义。

数据库结构,视图和效率

利用我对Views的介绍性知识,我认为我可以创建一些在每个课程中显示一行的属性,其中每个属性都是其自己的列。我不知道如何实现这一目标,甚至可能。

我对数据库结构不是最有信心,但是我按上述说明设置表的原因是因为在许多情况下,并非每门课程都会完成所有字段,因此我试图提高效率[是的,似乎好像我失败了]。

我以为使用当前结构,每个属性都将包含一个值,因此不会在表中造成浪费。或者,如果我有一个包含大量潜在属性的表,我会认为这会浪费空间。如果我不正确,我很高兴了解为什么我的理解是错误的。

最佳答案

首先,我什至从未听说过狮身人面像,也从未(显然)使用过它。但是,从数据库角度来看...

这样做多域列是一个糟糕的想法(我会追捕您并杀死您)。一方面,不可能对句点进行有意义的索引或排序。您还必须祈祷您不会获得带有文本数据的latitude属性(并且由于只能以编程方式进行增强,因此我将确保这种情况会发生)-这样做会导致所有基于距离的公式崩溃。说到位置,如果有人存储没有latitudelongitude会发生什么(请注意,无论您存储的是单个GeoLocation属性还是该对,这都是可能的)?

最好的选择是执行以下操作:


找出始终需要哪个attributes。这些属于course表(...大部分)。
对于每个相关的可选属性集,创建一个表。例如,location(尽管可能应该是必需的...),其中应包含纬度/经度,城市,州,地址,房间等。允许列为null(在集合中-添加约束)因此用户不能仅添加longitude而不可以添加latitude)。
为每组常见查询添加一个视图。即使(也许尤其是)如果您坚持使用当前设计,也可以使用视图。这促进了数据库的逻辑和物理实现之间的分离。 (这假定通过SQL进行搜索)然后,您可以通过指定view_column is null or view_column = input_parameter或任何一个来进行搜索。
对于加权搜索(假设动态加权),您的查询将需要使用left join(在视图内部-请对此进行记录),并使用准备好的语句主机参数(只是为自己节省了尝试自己逃避麻烦的麻烦) )。检查每组参数(例如,lat和long),然后将输入权重分配给新列(每个属性),可以将这些总和汇总为“ total”列(必须超过某个阈值)。




编辑:

使用视图:
对于您的结构,通常要做的是多次left joinattributes表(每个所需的属性一个),从attribute键关闭(它实际上应该是表的int FK;您不要'既不希望同时包含'title'和'Title',又加入course_id-value将作为选择的一部分。使用此技术,获得列的列表将很简单,然后您显然可以在Sphinx中进行加权。
问题是如果您需要进行任何数据转换-您打赌如果类型发生变化,您将能够找到所有转换。当使用强类型的列时,这在琐碎的(很可能是最后得到一个唯一命名的列)和不必要的(视图通常从查询的字段中获取它们的数据类型定义)之间;对于您的体系结构,您可能最终会发现太多的误报。

数据库效率:
没错,未填充的列浪费了空间。通常,当某些东西是可选的(ish)时,这意味着您可能需要一个附加表。这就是为什么我建议将位置拆分到它自己的表中的原因:这可以防止不需要位置的事件(...什么?)浪费空间,但是随后强制任何定义位置的事件来指定所有必需的位置信息。通过这种方式进行拆分还有一个额外的好处:如果多个事件都使用相同的位置(...,我们希望不是同一时间),那么交叉引用表将为您节省很多空间。比attributes表所能提供的方式更多(毕竟,您仍然必须存储每个事件的完整位置)。如果您仍然有很多“可选”属性,我听说NoSQL是为这类事情制作的(但是我没有真正研究过)。但是,除此之外,增加一个表的成本是微不足道的。内部数据的成本可能没有,但所需的空间要与存储的数据的感知值权衡。请记住,磁盘空间相对便宜-开发人员/维护人员的时间很昂贵。


  地址旁注:
  您可能要创建一个address表。这将与event信息完全脱离,并且将包括(除其他事项外)预先计算的纬度/经度(在建议的数据类型中-我不知道它是什么,但可以肯定的是,它不是逗号分隔的字符串) )。然后,您将有一个event_address表,该表将成为事件及其发生位置之间的交叉引用-如果存在其他信息(例如room),则应将其保存在location表中已引用(而不是直接引用address)。一旦计算出经/纬度值,就无需更改它。


对以后的经纬度更新的思考:
虽然您自己指定lat / long值会更好,但是您将需要使它们成为address表的必需部分(或作为纯lat / long only表的一部分/补充)。坦白地说,任何类型的多值列(定界列表)都在乞求麻烦-每次搜索它们时(除了其他相关问题之外),您都不得不继续解析它们。而且,当您将它们分开排成一排时,这对中的一个将最终掉线-如有必要,墨菲本人将亲自干预。另外,在与地址不同的时间更新它们将导致地址的经纬度对不匹配;最好的选择是在插入时进行计算(有许多Web服务可以为您找到此信息)。

多域表:
使用多域表,您基本上是在押注域密钥(attribute)将永远不会与值(err,value)不同步。我不在乎您会在某处以某种方式变好:在我的公司中,我们在旧版应用程序中拥有其中之一(它存储FK链接以及FK所引用的文件以及属性) 。有一次,在生产环境中安装了一个应用程序,该应用程序立即开始存储正确的文件链接,但是对于给定的属性类,FK链接到另一个文件。值得庆幸的是,另一个文件中有审核记录,可以将其撤消(...尽其所能)。

综上所述:
重新访问您的必需/可选数据。不要害怕为每个实体创建其他表,并为单个域创建每一列。您还将需要关系表。您可能还希望将审核数据(last_updated_time)放在一组单独的表中(单域表在这方面将有很大帮助)。

关于php - Sphinx搜索的数据库定义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7836051/

相关文章:

php - 如何将 session 变量添加到数据库中?

javascript - 将不属于表单一部分的 HTML 页面的值传递给 PHP 页面

mysql - 如何仅选择小于 'target' 值的最接近值?

mysql - 如何将多行合并为一行

SQL Server - 查找不删除临时表的 SP

php - 如何重命名 Symfony 项目?

php - Yii 表前缀 无法读取带有该前缀的表

php - 发送 STMT_PREPARE 数据包时出错。 PID=2

sql - CSV 回车字符

sql - 如何在MySQL中随机选择八个项目,每个项目都符合特定条件?