本文將向您介紹如何使用推薦過濾功能,實現推薦情境的按需定製,滿足使用者的特定瀏覽喜好。
一、背景介紹
在某些猜你喜歡情境當中,使用者可能會出於需求或自身喜好與經驗,只想要看到屬於特定品牌等擁有特定屬性的物品,此時可以使用推薦過濾功能,只要在用戶端埋點對應選擇邏輯,在服務端SDK請求推薦結果時加上要篩選的條件,即可擷取到希望返回的指定類型(比如指定類別、標籤、城市、作者等等)的物品。
實現情境:
以下為使用情境
例1:
當使用者在瀏覽民宿、酒店時,對地點等屬性有硬性需求,此時就可以選擇對應需求的tag來篩選推薦結果,讓使用者可以更加方便快捷的找到心儀的物品。(此功能同樣也可適用於行為資料較少的新使用者,通過使用者自身選擇來快速鎖定使用者喜好。)

例2:
新品活動頁面篩選使用者喜好品牌的活動產品:

使用者在瀏覽新品推薦的情境時,想要對自己感興趣的品牌進行過濾篩選。
可以看到,該功能可在部分已有情境(如新品、活動商品)的基礎上,疊加使用者根據自己喜好選擇的過濾條件,形成更加靈活、細分、可自由定製的個人化推薦結果。
二、使用方法
推薦過濾功能目前沒有控制台設定頁面,因為是在已有推薦情境的基礎上增加對物品屬性的過濾, 因此需要在請求推薦結果時,以添加參數的形式調用請求推薦結果的介面使用,具體方式為:
將表示過濾規則的JSON字串經過Base64編碼後,將編碼結果中的”+”、”/” 、”=”分別替換為”-”、”_” 、”.”,然後將此結果作為filter參數,請求推薦介面即可。
除了要求符合基本格式外,過濾規則中還要求:
總的單值過濾規則不超過10個
組合深度不超過3層(即第3層的所有過濾規則必須都是單值過濾規則)
阿里雲對URL的長度有限制,因此編碼之後的字串總長度不能過長,否則可能會引起SDK拋錯;
一般來說,只要遵循上述1、2要求,這個長度都不會超過限制。
此處SDK樣本位於文章末尾。
三、功能詳解
推薦過濾功能支援對物品的單個屬性欄位的單值過濾,也支援對多個屬性欄位的組合過濾。
單值過濾:
支援的過濾條件有三種類型:
包含/不包含(contain/not_contain),僅支援多重值欄位(多重值欄位是指可以用逗號分隔的字串欄位,比如tags, author)
相等/不相等(equal/not_equal,僅支援單值欄位(比如item_type, title, city)
類目匹配/類目不匹配(category_match/category_not_match),僅支援類目欄位(只有category_path),類目匹配只支援從頭開始,比如category_path=1_2_3_4,則只能匹配1、1_2、1_2_3、1_2_3_4,而不能匹配2_3、 3_4、2_3_4)
組合過濾:
對單值過濾或其他組合過濾的結果進行“且/或”的邏輯組合。 目前不同行業支援的推薦過濾欄位有所差異,具體支援推薦過濾的欄位如下:
電商行業:
單值欄位:
item_id,item_type,category_level,category_path,weight,cur_price,brand_id,shop_id,source_id
多重值欄位:
tags
內容行業: 單值欄位:
item_id,item_type,category_level,category_path,channel,weight,pub_id,source_id,country,city
多重值欄位:
tags,organization,author
新聞行業: 單值欄位:
item_id,item_type,category_level,category_path,channel,weight,pub_id,source_id,country,city
多重值欄位:
tags,organization,author
過濾規則通過一個JSON字串來表示,JSON格式的過濾規則的具體文法如下: 單值過濾:
{
"cond": "contain" | "not_contain" | "equal" | "not_equal"| "category_match" | "category_not_match", // 要進行的比較操作
"field": "<field_name>", // 要篩選的欄位名,如"tags"、"channel"等
"value": "<compare_value>" // 要篩選的目標值,如"軍事"、"周星馳"等
}組合過濾:
{
"join": "and" | "or",
"filters": [
{ 組合過濾規則 | 單值過濾規則 },
{ 組合過濾規則 | 單值過濾規則 },
...
]
}四、應用執行個體
例3:
如圖,假設當前產品為旅遊類電商,情境設定有“出行”、“酒店”等情境,其中“出行”情境中設定了“機票”、“火車票”、“汽車/船票”、“接送/租車”四個類目(category_path)的物品(item)。
使用者想要查看“出行”頁面下,“接送/租車”類目裡的“租車”物品,
使用者有額外需求是:能送車上門、是京牌、有倒車雷達,
根據需求,此處需要擷取推薦商品的請求為:在“出行_接送/租車”類目下,屬於“租車”類(假設用brand_id區分)的商品,但因使用者有額外需求,則需要使用到組合過濾功能,來滿足使用者一定的定製需求。
假設後面三項需求是在物品的tags欄位中作為屬性存放,則此處的推薦過濾運算式為:
( category_path 類目匹配 “出行_接送/租車 )AND ( brand_id = “租車”) AND
((tags 包含 “送車上門”) OR (tags 包含 “京牌”) OR (tags 包含 “倒車雷達”))
可用如下JSON格式的過濾條件查詢:
{
"join": "and",
"filters": [
{
"cond": "contain",
"field": "brand_id",
"value": "租車"
},
{
"cond": "category_match",
"field": "category_path",
"value": "出行_接送/租車"
},
{
"join": "or",
"filters": [{
"cond": "contain",
"field": "tags",
"value": "送車上門"
},
{
"cond": "contain",
"field": "tags",
"value": "京牌"
},
{
"cond": "contain",
"field": "tags",
"value": "倒車雷達"
}]
}]
}在發送請求時,使用如上的過濾條件即可。
在field相同的情況下可以進行簡寫,and用&,or用|串連。例如“送車上門”、“京牌”與“倒車雷達”的field都為tags,即可用"送車上門|京牌|倒車雷達"表示。
{
"join": "and",
"filters": [
{
"cond": "contain",
"field": "brand_id",
"value": "租車"
},
{
"cond": "category_match",
"field": "category_path",
"value": "出行_接送/租車"
},
{
"cond": "contain",
"field": "tags",
"value": "送車上門|京牌|倒車雷達"
}]
}SDK調用代碼範例
SDK調用程式碼範例:
@Data
private static abstract class BaseFilterRule {}
@EqualsAndHashCode(callSuper = true)
@Data
private static final class JoinFilterRule extends BaseFilterRule {
String join;
List<BaseFilterRule> filters = new ArrayList<>();
}
@EqualsAndHashCode(callSuper = true)
@Data
private static final class SingleFilterRule extends BaseFilterRule {
String cond;
String field;
String value;
}
public void testRecommendWithFilterDemo() throws ClientException {
JoinFilterRule rootRule = new JoinFilterRule();
rootRule.setJoin("and");
{
JoinFilterRule tagsRule = new JoinFilterRule();
tagsRule.setJoin("or");
{
SingleFilterRule rule = new SingleFilterRule();
rule.setCond("contain");
rule.setField("tags");
rule.setValue("小紅書");
tagsRule.getFilters().add(rule);
}
{
SingleFilterRule rule = new SingleFilterRule();
rule.setCond("contain");
rule.setField("tags");
rule.setValue("爆品");
tagsRule.getFilters().add(rule);
}
rootRule.getFilters().add(tagsRule);
}
{
SingleFilterRule rule = new SingleFilterRule();
rule.setCond("equal");
rule.setField("channel");
rule.setValue("美妝");
rootRule.getFilters().add(rule);
}
{
SingleFilterRule rule = new SingleFilterRule();
rule.setCond("not_equal");
rule.setField("category");
rule.setValue("促銷品");
rootRule.getFilters().add(rule);
}
{
SingleFilterRule rule = new SingleFilterRule();
rule.setCond("category_match");
rule.setField("category_path");
rule.setValue("女裝_裙子");
rootRule.getFilters().add(rule);
}
String filterRuleString = new Gson().toJson(rootRule);
filterRuleString = new String(Base64.getEncoder().encode(filterRuleString.getBytes()));
filterRuleString = filterRuleString.replaceAll("\\+", "-");
filterRuleString = filterRuleString.replaceAll("/", "_");
filterRuleString = filterRuleString.replaceAll("=", ".");
DefaultAcsClient client = createClient();
RecommendRequest request = new RecommendRequest();
request.setInstanceId(instanceId);
request.setSceneId(sceneId);
request.setUserId(userId);
request.putQueryParameter("filter", filterRuleString); // 添加filter參數
request.setReturnCount(2);
request.setAcceptFormat(FormatType.JSON);
RecommendResponse response = client.getAcsResponse(request);
System.out.println(String.format("got %d results", response.getResult().size()));
}