SpringBoot + MySQL + Elasticsearch 打造房产租赁信息搜索平台
·
《基于 SpringBoot + MySQL + Elasticsearch 的房产租赁信息搜索平台》
✅ 全文检索
✅ 中文分词
✅ 高亮 / 分页 / 筛选
✅ 数据同步
✅ 技术深度足够,答辩老师基本不会为难你

一、项目背景(论文 / 实战通用)
随着房产租赁市场的发展,用户对房源搜索的体验要求越来越高:
-
传统 SQL
LIKE查询性能差、匹配不智能 -
无法支持模糊、同义词、纠错
-
筛选条件多,组合复杂
-
数据量大时响应慢
本系统基于 SpringBoot + MySQL + Elasticsearch,实现:
✅ 房源信息全文检索
✅ 中文分词 & 高亮显示
✅ 多条件组合筛选
✅ MySQL ↔ ES 数据同步
✅ 近实时搜索
二、技术架构
前端(Vue / Thymeleaf)
↓
SpringBoot
├── 搜索接口(ES)
├── 房源管理(MySQL)
├── 数据同步模块
↓
MySQL(源数据)
Elasticsearch(全文索引)
|
技术 |
作用 |
|---|---|
|
SpringBoot |
快速开发 |
|
MyBatis |
ORM |
|
MySQL |
持久化存储 |
|
Elasticsearch 7.x |
全文检索 |
|
IK 分词器 |
中文分词 |
|
RestHighLevelClient |
ES Java 客户端 |
三、系统功能模块
房产租赁搜索平台
├── 房源管理模块
│ ├── 发布房源
│ └── 编辑 / 下架
├── 全文检索模块(⭐核心)
│ ├── 关键词搜索
│ ├── 高亮显示
│ └── 分页排序
├── 组合筛选模块
│ ├── 价格区间
│ ├── 区域 / 户型
│ └── 标签筛选
├── 数据同步模块
│ └── MySQL → ES
└── 用户模块
四、数据库设计(MySQL)
1️⃣ 房源表 house
CREATE TABLE house (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
title VARCHAR(100),
description TEXT,
price DECIMAL(10,2),
area DECIMAL(8,2),
room_count INT,
hall_count INT,
floor INT,
total_floor INT,
direction VARCHAR(20),
district VARCHAR(50),
address VARCHAR(200),
tags VARCHAR(200), -- 近地铁,精装修
status INT DEFAULT 1,
create_time DATETIME,
update_time DATETIME
);
五、ES 索引设计(⭐核心)
1️⃣ 创建索引 + IK 分词
PUT /house_index
{
"settings": {
"number_of_shards": 1,
"analysis": {
"analyzer": {
"ik_max_word": {
"type": "ik_max_word"
}
}
}
},
"mappings": {
"properties": {
"id": { "type": "long" },
"title": { "type": "text", "analyzer": "ik_max_word" },
"description":{ "type": "text", "analyzer": "ik_max_word" },
"price": { "type": "double" },
"area": { "type": "double" },
"roomCount": { "type": "integer" },
"district": { "type": "keyword" },
"tags": { "type": "keyword" },
"createTime": { "type": "date" }
}
}
}
2️⃣ 实体类 HouseES
@Data
@Document(indexName = "house_index")
public class HouseES {
private Long id;
private String title;
private String description;
private Double price;
private Double area;
private Integer roomCount;
private String district;
private List<String> tags;
private Date createTime;
}
六、数据同步(MySQL → ES)
方式一:同步写入(简单)
@Transactional
public void save(House house) {
// 1. 写 MySQL
houseMapper.insert(house);
// 2. 写 ES
HouseES es = convert(house);
restHighLevelClient.index(
new IndexRequest("house_index")
.id(house.getId().toString())
.source(JSON.toJSONString(es), XContentType.JSON)
);
}
方式二:定时同步(推荐)
@Scheduled(cron = "0 */5 * * * ?")
public void sync() {
List<House> list = houseMapper.selectUpdatedAfter(lastSyncTime);
for (House h : list) {
updateES(h);
}
}
七、全文检索核心实现(⭐重点)
1️⃣ 构建搜索条件
SearchRequest request = new SearchRequest("house_index");
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
// 1. 全文检索
if (StringUtils.isNotBlank(keyword)) {
boolQuery.must(QueryBuilders.multiMatchQuery(keyword, "title", "description"));
}
// 2. 价格区间
if (minPrice != null) {
boolQuery.filter(QueryBuilders.rangeQuery("price").gte(minPrice));
}
if (maxPrice != null) {
boolQuery.filter(QueryBuilders.rangeQuery("price").lte(maxPrice));
}
// 3. 区域
if (StringUtils.isNotBlank(district)) {
boolQuery.filter(QueryBuilders.termQuery("district", district));
}
// 4. 户型
if (roomCount != null) {
boolQuery.filter(QueryBuilders.termQuery("roomCount", roomCount));
}
2️⃣ 高亮 + 分页
// 高亮
HighlightBuilder highlight = new HighlightBuilder()
.field("title")
.preTags("<em>")
.postTags("</em>");
// 分页
SearchSourceBuilder source = new SearchSourceBuilder()
.query(boolQuery)
.highlighter(highlight)
.from((pageNum - 1) * pageSize)
.size(pageSize)
.sort("createTime", SortOrder.DESC);
request.source(source);
3️⃣ 解析结果
SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);
for (SearchHit hit : response.getHits()) {
HouseES house = JSON.parseObject(hit.getSourceAsString(), HouseES.class);
// 取高亮
Map<String, HighlightField> hl = hit.getHighlightFields();
if (hl.containsKey("title")) {
house.setTitle(hl.get("title").fragments()[0].string());
}
}
八、搜索接口(Controller)
@GetMapping("/search")
public R<PageResult<HouseES>> search(
@RequestParam(required = false) String keyword,
@RequestParam(required = false) Double minPrice,
@RequestParam(required = false) Double maxPrice,
@RequestParam(defaultValue = "1") Integer pageNum
) {
return R.ok(searchService.search(keyword, minPrice, maxPrice, pageNum));
}
九、搜索页面(前端示例)
<form action="/search">
<input type="text" name="keyword" placeholder="搜索小区/商圈/地铁">
价格:
<input name="minPrice" placeholder="最低价">
~
<input name="maxPrice" placeholder="最高价">
<button>搜索</button>
</form>
<div th:each="h : ${list}">
<h3 th:utext="${h.title}"></h3>
<p th:text="${h.description}"></p>
<span th:text="${h.price} + '元/月'"></span>
</div>
十、系统特色(⭐答辩亮点)
✅ Elasticsearch 全文检索
✅ IK 中文分词 + 高亮
✅ 多条件组合筛选
✅ MySQL ↔ ES 数据同步
✅ 近实时搜索
✅ 可扩展为租房平台核心搜索
十一、可扩展方向(工作量拉满)
✅ 地理位置搜索(geo_point)
✅ 自动补全 / 搜索建议(suggest)
✅ 竞价排名 / 房源置顶
✅ 搜索热词统计
✅ 分布式 ES 集群
✅ 接入大模型做智能问答
十二、毕设论文结构建议
|
章节 |
内容 |
|---|---|
|
第1章 |
绪论 |
|
第2章 |
相关技术 |
|
第3章 |
需求分析 |
|
第4章 |
系统设计(ES 索引设计) |
|
第5章 |
系统实现(全文检索核心) |
|
第6章 |
系统测试 |
|
第7章 |
总结与展望 |
更多推荐
所有评论(0)