【问题标题】:How to store real estate data in an elastic search?如何在弹性搜索中存储房地产数据?
【发布时间】:2021-03-09 18:28:18
【问题描述】:

我有房地产数据。我正在考虑将其存储到弹性搜索中,以允许用户实时搜索数据库。

我希望能够让我的用户按价格、地块大小、建造年份、卧室总数等关键字段进行搜索。但是,我还希望能够让用户按关键字或设施进行过滤,例如“有泳池”、“有水疗中心”、“停车位”、“社区”..

此外,我需要保留一份不同的房产类型、房产状态、学校、社区等列表,以便我可以创建下拉菜单供我的用户选择。

存储的数据结构应该是什么样的?如何维护不同学校、社区、类型的列表以使用该列表创建下拉菜单供用户选择?

我目前拥有的数据基本上是一个键/值对。我可以在将其存储到 Elastic Search 之前对其进行清理和标准化,但不知道什么是存储这些数据的好方法?

【问题讨论】:

    标签: elasticsearch elastic-stack elasticsearch-5


    【解决方案1】:

    根据您的问题,我将提供基线映射和带有构面/过滤器的基本查询供您开始使用。

    映射

    PUT test_jay
    {
      "mappings": {
        "properties": {
          "amenities": {
            "type": "keyword"
          },
          "description": {
            "type": "text"
          },
          "location": {
            "type": "geo_point"
          },
          "name": {
            "type": "text",
            "fields": {
              "keyword": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
          },
          "status": {
            "type": "keyword"
          },
          "type": {
            "type": "keyword"
          }
        }
      }
    }
    

    我们将使用“关键字”字段类型作为您将始终进行精确匹配的字段,例如下拉列表。

    对于我们只想像描述这样的全文搜索的字段,我们使用“text”类型。在某些情况下,比如标题,我希望同时拥有这两种字段类型。

    我创建了一个 location geo_type 字段,以防您想将您的房产放在地图中或进行基于距离的搜索,例如附近的房屋。

    对于便利设施,关键字字段类型足以存储一系列便利设施。

    提取文档

    POST test_jay/_doc
    {
      "name": "Nice property",
      "description": "nice located fancy property",
      "location": {
        "lat": 37.371623,
        "lon": -122.003338
      },
      "amenities": [
        "Pool",
        "Parking",
        "Community"
      ],
      "type": "House",
      "status": "On sale"
    }
    

    记住关键字字段区分大小写!

    搜索查询

    POST test_jay/_search
    {
      "query": {
        "bool": {
          "must": {
            "multi_match": {
              "query": "nice",
              "fields": [
                "name",
                "description"
              ]
            }
          },
          "filter": [
            {
              "term": {
                "status": "On sale"
              }
            },
            {
              "term": {
                "amenities":"Pool"
              }
            },
            {
              "term": {
                "type": "House"
              }
            }
          ]
        }
      },
      "aggs": {
        "amenities": {
          "terms": {
            "field": "amenities",
            "size": 10
          }
        },
        "status": {
          "terms": {
            "field": "status",
            "size": 10
          }
        },
        "type": {
          "terms": {
            "field": "type",
            "size": 10
          }
        }
      }
    }
    

    多重匹配部分将在标题和描述字段中进行全文搜索。您正在使用常规搜索框填充此内容。

    然后过滤器部分由下拉列表填充。

    查询响应

    {
      "took" : 1,
      "timed_out" : false,
      "_shards" : {
        "total" : 1,
        "successful" : 1,
        "skipped" : 0,
        "failed" : 0
      },
      "hits" : {
        "total" : {
          "value" : 1,
          "relation" : "eq"
        },
        "max_score" : 0.2876821,
        "hits" : [
          {
            "_index" : "test_jay",
            "_type" : "_doc",
            "_id" : "zWysGHgBLiMtJ3pUuvZH",
            "_score" : 0.2876821,
            "_source" : {
              "name" : "Nice property",
              "description" : "nice located fancy property",
              "location" : {
                "lat" : 37.371623,
                "lon" : -122.003338
              },
              "amenities" : [
                "Pool",
                "Parking",
                "Community"
              ],
              "type" : "House",
              "status" : "On sale"
            }
          }
        ]
      },
      "aggregations" : {
        "amenities" : {
          "doc_count_error_upper_bound" : 0,
          "sum_other_doc_count" : 0,
          "buckets" : [
            {
              "key" : "Community",
              "doc_count" : 1
            },
            {
              "key" : "Parking",
              "doc_count" : 1
            },
            {
              "key" : "Pool",
              "doc_count" : 1
            }
          ]
        },
        "type" : {
          "doc_count_error_upper_bound" : 0,
          "sum_other_doc_count" : 0,
          "buckets" : [
            {
              "key" : "House",
              "doc_count" : 1
            }
          ]
        },
        "status" : {
          "doc_count_error_upper_bound" : 0,
          "sum_other_doc_count" : 0,
          "buckets" : [
            {
              "key" : "On sale",
              "doc_count" : 1
            }
          ]
        }
      }
    }
    

    使用查询响应,您可以为将来的过滤器填充构面。

    我建议您尝试一下,然后再提出更具体的问题。

    【讨论】:

    • 非常感谢您的帮助!那么地址、价格、ListedDate 等其他信息呢?我应该在弹性搜索中存储多少信息有限制吗?我正在考虑将所有 MLS 数据直接存储到没有 RDBM 的弹性搜索中。另外,如何存储状态字段以便能够创建下拉菜单。
    • Elasticsearch 有 1000 个字段的限制,所以你会很好。我认为您可以遵循相同的准则:如果要进行全文搜索,请使用“文本”类型。如果您想创建一个使用“关键字”类型的下拉列表。对于价格,elasticsearch 建议使用 scaled_float 但任何数字类型都允许您进行范围查询elastic.co/guide/en/elasticsearch/reference/current/number.html
    • 所以对于任何关键字类型(如状态、类型、社区)都将存储到不同的端点/索引中,以便可以将其作为不同的列表进行检索?能够限制连接用户提交数据怎么样?比如如果我有一个源字段,我可以说用户 A 只能搜索源 A 和 B,而用户 B 只能搜索源 B?
    • 如果您查看我在最后回复中发布的查询,您可以看到“聚合”。每个桶键是该字段的唯一值,而 doc_count 字段是具有该字段值的文档的数量。这样您就可以构建典型的构面 [X] 状态 1 (22) [X] 状态 2 (10) 其中 22 和 10 是文档数量
    • 我没有得到第二个问题。当您实际说出您想要做什么而不是说“用户 A 搜索源 B”时,会容易得多。您可以按源添加额外的字段,或创建不同的索引。没有上下文很难说
    猜你喜欢
    • 2022-01-25
    • 1970-01-01
    • 2019-08-26
    • 1970-01-01
    • 2016-10-15
    • 2012-09-07
    • 1970-01-01
    • 2023-03-19
    • 1970-01-01
    相关资源
    最近更新 更多