注:在完成mcn功能的时候,现有的数据结构和方式都不能完成相应的需求,所以通过调研使用nested对象来实现。
具体需求:mcn存在主账号和子帐号。同时一个主账号会对应多个子帐号,一个子帐号也会对应多个主账号,存在一种网状的对应关系。原有的数据结构都不能很好的表达这种对应关系,所以需要使用nested对象。
mapping的创建语句:
POST /subscribe_wemedia_info/wemedia_info/_mapping?pretty
{
"wemedia_info": {
"properties": {
"mcn": {
"type": "nested",
"properties":{
"mainWemediaId":{"type":"keyword"},
"contractId":{"type":"keyword"},
"contractState": {"type":"integer"}
}
}
}
}
}
设计方案:
我们以每一个子帐号为单元,在该子帐号上存储它和所有主账号直接的关系,其在每个子帐号上存储的样子大致如下:
"mcn": [
{
"contractState": 1,
"mainWemediaId": "W7619921043901497107",
"contractId": "C5935530003484723955"
},
{
"contractState": 1,
"mainWemediaId": "W7619921043901497107",
"contractId": "C5935530003484723955"
}
]
javaAPI的搜索方式:
public SearchResult searchMCNMember(QueryMCNMemberParamDTO queryMCNMemberParamDTO, boolean isPage) throws JsonProcessingException {
QueryElasticMCNMemberDTO queryElasticMCNMemberDTO = new QueryElasticMCNMemberDTO(queryMCNMemberParamDTO);
SearchRequestBuilder searchRequestBuilder = elasticSearchService.prepareSearch(SUBSCRIBE_WEMEDIA_INDEX,
SUBSCRIBE_WEMEDIA_TYPE);
BoolQueryBuilder totalBoolQuery = QueryBuilders.boolQuery();
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
if (queryElasticMCNMemberDTO.getTname() != null) {
QueryBuilder query = QueryBuilders.matchQuery("tname", queryElasticMCNMemberDTO.getTname());
totalBoolQuery.must(query);
}
if (queryElasticMCNMemberDTO.getOnlineState() !=null && queryElasticMCNMemberDTO.getOnlineState()>= 0) {
QueryBuilder query = QueryBuilders.termQuery("onlineState", queryElasticMCNMemberDTO.getOnlineState());
totalBoolQuery.must(query);
}
if (queryElasticMCNMemberDTO.getContractState() != null && queryElasticMCNMemberDTO.getContractState()>= 0) {
QueryBuilder query = QueryBuilders.termQuery("mcn.contractState", queryElasticMCNMemberDTO.getContractState());
boolQueryBuilder.must(query);
}
if (queryElasticMCNMemberDTO.getContractId() != null) {
QueryBuilder query = QueryBuilders.termQuery("mcn.contractId", queryElasticMCNMemberDTO.getContractId());
boolQueryBuilder.must(query);
}
if (queryElasticMCNMemberDTO.getMainWemediaId() != null) {
QueryBuilder query = QueryBuilders.termQuery("mcn.mainWemediaId", queryElasticMCNMemberDTO.getMainWemediaId());
boolQueryBuilder.must(query);
}
NestedQueryBuilder queryBuilder = QueryBuilders.nestedQuery("mcn",boolQueryBuilder, ScoreMode.Avg);
totalBoolQuery.must(queryBuilder);
// 输出结果
searchRequestBuilder.setQuery(totalBoolQuery);
if (isPage) {
searchRequestBuilder.setFrom(queryElasticMCNMemberDTO.getOffset()).setSize(queryElasticMCNMemberDTO.getSize());
}
return elasticSearchService.getSearchResult(searchRequestBuilder);
}
kibana搜索方式:
GET subscribe_wemedia_info/wemedia_info/_search
{
"from" : 0,
"size" : 20,
"query" : {
"bool" : {
"must" : [
{
"match" : {
"tname" : {
"query" : "虎嗅网",
"operator" : "OR",
"prefix_length" : 0,
"max_expansions" : 50,
"fuzzy_transpositions" : true,
"lenient" : false,
"zero_terms_query" : "NONE",
"boost" : 1.0
}
}
},
{
"nested" : {
"query" : {
"bool" : {
"must" : [
{
"term" : {
"mcn.contractState" : {
"value" : 1,
"boost" : 1.0
}
}
},
{
"term" : {
"mcn.mainWemediaId" : {
"value" : "W4211537089812971765",
"boost" : 1.0
}
}
}
],
"disable_coord" : false,
"adjust_pure_negative" : true,
"boost" : 1.0
}
},
"path" : "mcn",
"ignore_unmapped" : false,
"score_mode" : "avg",
"boost" : 1.0
}
}
]
}
}
}
● nested对象的更新
更新需要先将mcn数据取出来,然后找到相应的要修改的地方,修改之前在回填回去。
java实现:
List esMcnVos = objectMapper.convertValue(map.get("mcn"), new TypeReference>() {});
可以在list上直接添加或找到要修改的地方。