如何设置具有多个实体绑定的 ElasticSearch 索引结构

Posted

技术标签:

【中文标题】如何设置具有多个实体绑定的 ElasticSearch 索引结构【英文标题】:How to setup ElasticSearch index structure with multiple entity bindings 【发布时间】:2016-08-23 06:18:11 【问题描述】:

最近,我开始在使用 mysqlphp 编写的遗留电子商务应用程序中实现 ElasticSearch (ES)。我对所有这些东西完全陌生,阅读文档很好,但我真的需要有经验的人给我建议。

从 ES 文档中,我能够设置一个新集群,并且我还发现河流已被弃用并且应该被替换,因此我将它们替换为 Logstash 和 JDBC MySQL 连接器。

此时我有:

弹性搜索 Lo​​gstash JDBC MySQL 驱动程序 MySQL 服务器

应用程序的数据库结构并不是最优的,而且很难替换,但我想以最好的方式将它复制到 ES 索引中。

数据库结构:

产品

+-------------------------------+-------+--------+
|              Id               | Title | Price  |
+-------------------------------+-------+--------+
| 00c8234d71c4e94f725cd432ebc04 | Alpha | 589,00 |
| 018357657529fef056cf396626812 | Beta  | 355,00 |
| 01a2c32ceeff0fc6b7dd4fc4302ab | Gamma | 0,00   |
+-------------------------------+-------+--------+

标志

+------------+-------------+
|     Id     |    Title    |
+------------+-------------+
| sellout    | Sellout     |
| discount   | Discount    |
| topproduct | Top Product |
+------------+-------------+

flagsProducts(n:m 支点)

+------+-------------------------------+------------+------------+
|  Id  |           ProductId           |   FlagId   | ExternalId |
+------+-------------------------------+------------+------------+
| 1552 | 00c8234d71c4e94f725cd432ebc04 | sellout    | NULL       |
| 2845 | 00c8234d71c4e94f725cd432ebc04 | topproduct | NULL       |
| 9689 | 018357657529fef056cf396626812 | discount   | NULL       |
| 4841 | 01a2c32ceeff0fc6b7dd4fc4302ab | discount   | NULL       |
+------+-------------------------------+------------+------------+

那些字符串 ID 完全是一场灾难(但我现在必须处理它们)。一开始我以为我应该对ES做一个扁平结构的Products索引,但是多实体绑定呢?

【问题讨论】:

如果你想将你的mysql数据移动到ES:sysadminci.wordpress.com/2016/01/06/… 扁平数据结构似乎是迄今为止最好的方法。您对此索引有什么特殊的查询要求吗?考虑 ES 中的数据结构意味着也要考虑要使用的查询。 @falnyr,您在过去 7 天内没有就您的问题发表意见。您还需要更多信息吗? 对不起各位,只是在处理一些其他的东西 atm,我会尽快设置它,以便我看看有什么不清楚的地方。 【参考方案1】:

这是一个很好的开始!

我肯定会将其全部展平(即denormalize)并提出如下所示的产品文档。这样,您只需为每个产品创建一个flags 数组,就可以摆脱产品和标志之间的 N:M 关系。因此查询这些标志会更容易。


   "id": "00c8234d71c4e94f725cd432ebc04",
   "title": "Alpha",
   "price": 589.0,
   "flags": ["Sellout", "Top Product"]


   "id": "018357657529fef056cf396626812",
   "title": "Beta",
   "price": 355.0,
   "flags": ["Discount"]


   "id": "01a2c32ceeff0fc6b7dd4fc4302ab",
   "title": "Gamma",
   "price": 0.0,
   "flags": ["Discount"]

产品映射类型如下所示:

PUT products

    "mappings": 
        "product": 
            "properties": 
                "id": 
                    "type": "string",
                    "index": "not_analyzed"
                ,
                "title": 
                    "type": "string"
                ,
                "price": 
                    "type": "double",
                    "null_value": 0.0
                ,
                "flags": 
                    "type": "string",
                    "index": "not_analyzed"
                
            
        
    

由于您已经有了 logstash jdbc 输入,您所缺少的只是获取产品和相关标志的正确 SQL 查询。

  SELECT p.Id as id, p.Title as title, p.Price as price, GROUP_CONCAT(f.Title) as flags
    FROM Products p
    JOIN flagsProducts fp ON fp.ProductId = p.Id
    JOIN Flags f ON fp.FlagId = f.id
GROUP BY p.Id

这会让你得到这样的行:

+-------------------------------+-------+-------+---------------------+
| id                            | title | price | flags               |
+-------------------------------+-------+-------+---------------------+
| 00c8234d71c4e94f725cd432ebc04 | Alpha |   589 | Sellout,Top product |
| 018357657529fef056cf396626812 | Beta  |   355 | Discount            |
| 01a2c32ceeff0fc6b7dd4fc4302ab | Gamma |     0 | Discount            |
+-------------------------------+-------+-------+---------------------+

使用 Logstash 过滤器,您可以将 flags 拆分为一个数组,一切顺利。

【讨论】:

这是否意味着“标志”映射应该是数组而不是字符串,因为我应用了 logstash 过滤器? String 没问题,ES 会为你创建一个字符串数组。

以上是关于如何设置具有多个实体绑定的 ElasticSearch 索引结构的主要内容,如果未能解决你的问题,请参考以下文章

NestJS + MySQL:如何在不设置实体的情况下连接多个数据库

实体框架 - 具有挑战性的设置包括多个主键,以及与外部表的多个关联

如何将同一个xib文件绑定到不同的核心数据实体

如何设置核心数据实体之间的关系?

使用跨越多个实体的核心数据绑定在 Cocoa 中实现父->子向下钻取

如何过滤具有多个条件的托管对象实体