【问题标题】:How to use ElasticSearch for product search (filtering) in eShop?如何在 eShop 中使用 ElasticSearch 进行产品搜索(过滤)?
【发布时间】:2020-11-22 00:40:09
【问题描述】:

我是 ElasticSearch 的新手! 我有一个拥有超过 1,000,000 种产品的 eShop(使用 Laravel),每个产品在 product 表中都有一些属性,例如名称、描述、价格……以及其他表中的一些其他属性,例如 categoriesoptionstags, addresses, rating, brands, ... 它们在单独的表格中,它们将通过many-to-many关系加入产品!

所以我想快速可靠地搜索具有许多过滤器的产品!像亚马逊!例如,用户将能够找到具有特殊类别、标签、选项的产品......!就像你现在在 mysql 中一样,我必须多次使用 WHERE EXISTSINNER JOIN 和 ... 由于产品数量太大,这些查询既昂贵又慢!所以我发现弹性搜索可以解决这种情况!它喜欢使用大数据!

我读过它!现在我有了一个想法,但我不确定这是不是正确的方法?

我说我们可以将每个categoriesoptionstagsaddressesratingbrands 作为 json 对象存储在弹性搜索中,仅在每个 UPDATE/STORE laravel 应用程序中的事件!在 mysql 中,它们具有分离的表和它们的多对多关系!但是我们不必为它们中的每一个(表)定义一个索引,然后像 mysql 方式一样重复以弹性方式加入它们!

在弹性搜索中,我们将为产品提供这种模式:

"id" : 782,
"title" : "dmorar",
"price" : "11000.00",
"options" : [ the ids of the product's tags ],
"categories" : [ the ids of the product's categories],
"tags" : [ the ids of the product's tags ],
"addresses" : [ the ids of the product's addresses]

这是一个例子:

  {
    "_index" : "so_product",
    "_type" : "_doc",
    "_id" : "1099",
    "_score" : 1.0,
    "_source" : {
      "id" : 782,
      "title" : "dmorar",
      "price" : "11000.00",
      "created_at" : "2020-07-30T14:01:09.000000Z",
      "updated_at" : "2020-07-30T14:01:09.000000Z",
      "options" : [
        75,
        955,
        480,
        351,
        285
      ],
      "categories" : [
        944,
        421
      ],
      "tags" : [
        210,
        198,
        648,
        976,
        10,
        553,
        624,
        967,
        726,
        121,
        797
      ],
      "addresses" : [
        119,
        43,
        140,
        1713,
        855,
        1515,
        958
      ]
    }
  },
  {
    "_index" : "so_product",
    "_type" : "_doc",
    "_id" : "1344",
    "_score" : 1.0,
    "_source" : {
      "id" : 429,
      "title" : "ethyl.wehner",
      "price" : "89000.00",
      "created_at" : "2020-07-30T13:59:02.000000Z",
      "updated_at" : "2020-07-30T13:59:02.000000Z",
      "options" : [
        121,
        195,
        348
      ],
      "categories" : [
        372,
        315,
        869,
        544,
        645,
        803,
        564
      ],
      "tags" : [
        347,
        797
      ],
      "addresses" : [
        609,
        1477,
        187,
        1479
      ]
    }
  },
  {
    "_index" : "so_product",
    "_type" : "_doc",
    "_id" : "1370",
    "_score" : 1.0,
    "_source" : {
      "id" : 358,
      "title" : "cicero.casper",
      "price" : "67000.00",
      "created_at" : "2020-07-30T13:58:37.000000Z",
      "updated_at" : "2020-07-30T13:58:37.000000Z",
      "options" : [
        665,
        28,
        488,
        384,
        547,
        877
      ],
      "categories" : [
        508,
        201
      ],
      "tags" : [
        325,
        472,
        595,
        797,
        943,
        948,
        803,
        136,
        288,
        275,
        574,
        390
      ],
      "addresses" : [
        691,
        1637,
        534,
        770,
        499,
        1086,
        430,
        1365,
        1325
      ]
    }
  }

以这种方式购买这样的搜索查询可以让用户完全控制使用他想要的每个过滤器,而且速度很快:

GET so_product/_search
{
  "query": {
      "bool": {
      "must": [
        {
            "term": {
            "options": 5
            }
        }, 
        {
            "term": {
            "options": 695
            }
        } ,
        {
            "term": {
            "categories": 523
            }
        }
         ,
        {
            "term": {
            "addresses": 116
            }
        } 
        ,
        {
            "term": {
            "tags": 797
            }
        } 
      ]
    }
  }
}

但正如我之前所说,我不确定这是否正确?如果不正确,标准方法是什么? amazon 是如何实现这个搜索过滤器的?

【问题讨论】:

    标签: mysql laravel elasticsearch search


    【解决方案1】:

    您的 ES 架构没问题,但您可以通过将 ID(如标签 ID、类别 ID 等)替换为其实际值来改进它。通过这种方式,您可以根据输入的查询从 ElasticSearch 中获取侧边栏过滤器和构面,而且您可以比从 MySQL 中获取它们更快地检索它们。

    由于您使用的是 Laravel,因此您可以在创建、更新产品或将类别、标签等任何属性添加到产品时使用事件来反映对弹性搜索的更改。

    【讨论】:

    • 对于分面搜索,UI 大多同时具有 id 和值。因此,在这种特殊情况下,分面搜索也可以由 id 提供支持。添加值还会在更改类别、标签等时增加更新成本。除非需要,否则我会建议不要使用名称。
    【解决方案2】:

    我的观察:

    Elastic Search 是一个很棒的工具:

    1. 搜索

    2. 实时聚合

    注意事项:

    1. 如果最终一致性没问题,请使用它。例如,索引文档可能无法立即用于搜索
    2. 以非规范化格式存储搜索所需的数据。
    3. ES 有一些细微差别,例如无法增加主分片的数量,请确保有一个适合您的值。

    您的用例:

    1. Mysql 不能很好地为您的应用程序提供搜索服务(使用您拥有的数据)。
      • ES 是搜索的好选择
    2. 您的架构看起来不错。确保明确定义索引映射。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-04-25
      • 1970-01-01
      • 2021-04-18
      • 1970-01-01
      • 1970-01-01
      • 2021-07-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多