首页 > 解决方案 > 如何在弹性搜索中存储房地产数据?

问题描述

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

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

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

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

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

标签: elasticsearchelastic-stackelasticsearch-5

解决方案


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

映射

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"
      }
    }
  }
}

我们将使用“关键字”字段类型,您将始终像下拉列表一样进行精确匹配。

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

我创建了一个 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
        }
      ]
    }
  }
}

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

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


推荐阅读