卫海波@贝壳找房 贝壳产品技术

贝壳找房APP给用户提供了海量房源的搜索查询功能,但是网站存量房源并不能完全满足用户的找房需求,用户希望可以及时获取新上房源的实时提醒。目前贝壳找房APP提供的房源新上实时推送有两个维度:基于关注小区的房源新上和基于搜索订阅条件的房源新上。

基于关注小区的房源新上只能给用户推送关注小区的新上房源,覆盖小区有限,而且用户买房时,在关注小区之前通常是通过筛选条件锁定某区域范围、某价格区间、某面积区间之类的房源。基于搜索订阅条件的房源新上恰好给用户提供了该场景下的房源新上的通路。

本文将重点讲解如何实现基于用户搜索订阅条件的房源新上实时推送方案。

1 核心难点

解决房源新上实时推送给订阅搜索条件用户,核心难点在于当一个房源上架时,如何在海量复杂的用户订阅条件中快速找到哪些用户的订阅条件能命中该房源。

如图1所示,贝壳找房APP给用户提供了各种筛选项,从区域地铁、价格、面积、标签等等。同类条件可以多选,不同类条件可以随意组合,这些筛选项可以组合出复杂多变的筛选条件,用数学的排列组合来计算,每一类条件的排列组合是A=C(a,1)+ C(a,2)+…+C(a,a) , 而不同类的条件组合是 SUM=A * B * … * N,仅以北京为例,假设同类条件只选择一个,即A= C(a,1),那么SUM≈153亿种条件组合。目前贝壳APP的用户已经选择了约500万条件作为自己的搜索订阅条件,且持续增长中。

面对如此海量且复杂的搜索订阅条件,当一个房源新上时,如何快速找到哪些用户的搜索条件与该房源有关并且推送给用户,是该方案要核心解决的难点问题。

图1. 贝壳找房筛选条件选项

2 产品功能介绍

在介绍方案之前,先看一下产品形态。当用户通过选择某些条件来筛选房源并且订阅该搜索条件,比如订阅条件是“北京市944-1416万二室”,如图2:

图2. 用户搜索房源并订阅搜索条件

当北京市房源新上时,比如该房源属性是980万2室,符合上述用户订阅的条件“北京市944-1416万二室”,则实时推送给该用户。如图3:

图3. 房源新上推送给符合订阅条件用户

用户点击PUSH进入推送消息落地页,可以及时查询房源信息,可与经纪人进行及时沟通。如图4:

图4. 符合用户订阅条件的实时feed流

由以上场景可以看出,用户订阅了”北京市944-1416万二室“搜索条件,当北京新上了一套980万2室70平米的房源,满足了该用户订阅的条件,则实时给用户进行了推送。

3 解决方案

贝壳找房APP房源筛选功能是通过用户搜索条件召回房源,而房源新上推送是通过房源召回检索条件,这两个场景虽然是相反的关系,但是也有相通性。在介绍基于房源召回搜索条件之前,先介绍贝壳找房APP是如何基于用户搜索条件召回房源的。

3.1 基于搜索条件召回房源

3.1.1 搜索条件描述

贝壳找房APP给用户提供了多种类别的筛选条件(此图位贝壳找房网页、APP条件跟这个相同),如图1所示。从图1可以看出,贝壳找房APP提供的筛选种类丰富,包含了地理位置、房源价格、面积、特色标签、楼盘属性等筛选类别。基本可以涵盖用户的房源筛选需求,所有这些条件都可以进行组合筛选。

在实现上,我们给每类条件的每个选项一个唯一标识,每个item用“字母+id”的形式表示。

比如东城区用d23008614表示,其中d代表城区、23008614是该城区的唯一id,价格是p、面积是a、房型是l,对于这种没有楼盘属性的词,业务则自己分配id,按照基础数字递增,比如200万以下:p1,一室:l1,50平米以下:a1。

通过这种组合,用户在筛选各种条件后,将每个item条件进行拼接,则组成用户的筛选条件。比如用户的搜索条件是d23008614l3p5,即为用户搜索”东城3室400-500万”的房源。服务端保存的用户订阅的条件也是“d23008614l3p5”该值。

3.1.2 房源属性数据结构描述

上一小节我们描述了用户的条件组成,本节介绍一个房源的唯一描述。每一个房源有自己单独的唯一属性,比如地理位置信息、价格、面积等等,我们通过不同字段对房源进行描述,并建立房源的数据结构。最后将该房源的数据结构存储在ES索引里。

我们设置一组通用的字段描述,如果该房源无该属性,则填充默认值为NULL即可。房源属性字段描述如下:

3.1.3 搜索条件召回房源

在3.1.1小节中,用户搜索完一个条件,选中的条件比如是d23008614l3p5,后端拿到该条件进行解析成房源属性对应的字段分别为:

后端解析完之后转成对应的检索查询条件,如下:

通过以上检索语法就可以召回用户条件“d23008614l3p5”命中的房源,即实现了用户搜索条件召回房源的功能。

3.2 基于房源召回订阅条件

在没有基于房源召回订阅条件之前,我们的基于订阅的房源新上推送是采用以下传统的搜索订阅房源新上推送方式。

3.2.1 传统的搜索订阅房源新上推送

在3.1我们介绍了基于搜索条件召回房源,传统的基于搜索订阅新上房源则采取如下方案:

图5. 传统搜索订阅推送方案

该方案虽然可以实现符合用户订阅条件的房源新上推送,但是也有着很明显的缺点,主要有以下几个方面:

3.2.2 基于房源新上实时召回订阅条件

基于房源召回命中的订阅条件与3.1是相反的,借鉴3.1索引的思路,我们采取以下方案来实现房源召回命中的订阅条件。

图6. 实时订阅索引构建和房源新上实时推送

在3.1.1中我们可以看到目前贝壳APP提供的搜索筛选项,3.1.2我们看到了房源字段的描述。我们借助这两个维度信息,用以下这些字段来描述一个用户的搜索条件。

如果用户选择了该选项,则字段值为用户实际选择的条件值,如果用户没有选择该选项,则给默认值-1。

我们将用户的选择的条件主要分为以下两类:

(1)有限枚举集合:比如城区、商圈、朝向等等,这种条件直接填充用户选择的值即可,如果用户没有选择该条件,则填充-1,代表用户未选择该条件,比如用户选择东城满五房源,可以用以下字段描述:

(2)对于价格和面积这类不确定区间范围字段产品给用户提供两种选择:

方式一:有限可枚举区间段,比如400-500万,600-700万,1000万以上,区间段用户可以间隔选择多个。

区间段有个分界值,比如价格是1000万,即1000万以下是有多个区间段组成,而1000万以上就只有一个1000万以上选项。

方式二:用户自定义输入一个区间,比如123-789万或者800-2000万

这两种方式中,用户只能选择其中一种方式进行筛选,面积也同理。

针对像价格面积存在有限区间段且可以间隔选择以及无限区间的情况,我们设置三个字段来标识用户的条件,以价格举例,分别是priceEnum、priceMin、priceMax。priceEnum主要解决分界值以下价格区间段选择存在断档可能,priceMin、priceMax主要解决超分界值自定义区间。

该三个字段涵盖了用户关于价格的所有筛选场景,主要有以下三种描述:

  1. 当用户没有选择价格时:

  1. 当用户选择的价格,且价格没有超过分界值,比如选择了200-300万,400-500万:

  1. 当用户选择了价格,且价格超过了分界值,比如选择了价格区间,比如800-1200万:

面积的原理同上,分别是areaEnum、areaMin、areaMax,分界值是200平米。

通过以上工作,我们将用户的搜索条件转换成房源维度的索引信息,比如一开始的用户订阅条件 ”944-1416万,2室“ 搜索条件转化为索引信息如下:

将转换完的订阅条件存储到用户的订阅条件索引里。

接下来到了方案最后一部分,当房源新上时,如何从用户的订阅条件索引里召回符合条件的数据。

当一个房源新上时,通过3.1.2获取房源的属性字段,然后在3.2.1构建的用户订阅条件中查询,查询方式如下:

  1. 除了价格、面积的其他字段,比如该房源卧室数量为2,则查询如下:

该查询是即为查询用户订阅条件中的bedroomNum包含为-1或者2,意味着用户订阅条件中没有选择卧室条件或者选中卧室条件包含2室。其他条件类似。

  1. 价格、面积类,因为涉及到枚举字段和最小值、最大值方式。

如果房源价格为980万,在价格分界值1000万以下,则查询条件如下:

该查询是即为查询用户订阅条件中的priceEnum值包含-1或者980,意味着用户订阅条件中没有选择价格条件或者选中价格条件包含980万。

如果房源价格为1299万,在分界值1000万以上,则查询条件为:

该查询即为查询用户条件中最小价格小于等于1299,最高价格大于等于1299(因为如果用户没有选中价格条件的话,priceMin=0,priceMax=2147483647 也满足此条件)。

通过以上的分析,当一个房源新上时,通过获取房子字段的标准信息值,查询用户的订阅条件索引的语法如下:

通过以上查询,可以获取到符合该房源的用户订阅条件,然后直接推送给用户即可。而一次查询只需要200ms左右的时间。基于以上方案,我们就实现了基于用户订阅条件的房源新上实时推送方案。

该方案巧妙的应用了ES的查询功能,将用户的搜索条件转换为与房源关联的数据结构,当房源新上时,实现了通过房源反查命中哪些用户的订阅条件,快速实现了消息实时推送。

相对于传统的搜索订阅推送,该推送方案有如下优点:

以上只是C端信息服务的其中一部分内容,在贝壳