第三题,参考官方文档写的

来源:10-15 【勤于思考,夯实学习成果】搜索2.0架构之搜索接入

波粒二象性max

2020-03-11

老师我在看官方文档的时候看到脚本好像分为store,和我们这种,官方好像建议有乘法的先存一下再调用,我们这种是ES内置的吗?不需要先存下吧。

 @Override
    public Map<String, Object> searchES(BigDecimal longitude, BigDecimal latitude, String keyword, Integer orderBy, Integer categoryId, String tags) {

        Map<String, Object> result = new HashMap<>(16);

        SearchRequest searchRequest = new SearchRequest("shop");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

        //function_score

        //1.1、构建bool query
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.must(QueryBuilders.termQuery("seller_disabled_flag", 0));
        //关键字
        if (StrUtil.isNotEmpty(keyword)) {
            boolQueryBuilder.must(QueryBuilders.matchQuery("name", keyword).boost(0.1f));
        }
        if (null != categoryId) {
            boolQueryBuilder.must(QueryBuilders.termQuery("category_id", categoryId));
        }
        if (StrUtil.isNotEmpty(tags)) {
            boolQueryBuilder.must(QueryBuilders.termQuery("tags", tags));
        }
        //默认排序
        if (null == orderBy) {
            FunctionScoreQueryBuilder.FilterFunctionBuilder[] filterFunctionBuilders = new FunctionScoreQueryBuilder.FilterFunctionBuilder[3];
            //2.1、构建高斯函数
            String origin = longitude + "," + latitude;
            ScoreFunctionBuilder<GaussDecayFunctionBuilder> gaussDecayFunctionBuilder = new GaussDecayFunctionBuilder("location", origin, "100km", "0km", 0.5);
            gaussDecayFunctionBuilder.setWeight(9);
            filterFunctionBuilders[0] = new FunctionScoreQueryBuilder.FilterFunctionBuilder(gaussDecayFunctionBuilder);
            //2.2、构建自定义的remark_score
            ScoreFunctionBuilder<FieldValueFactorFunctionBuilder> remarkScoreFunctionBuilder = new FieldValueFactorFunctionBuilder("remark_score");
            remarkScoreFunctionBuilder.setWeight(0.2f);
            filterFunctionBuilders[1] = new FunctionScoreQueryBuilder.FilterFunctionBuilder(remarkScoreFunctionBuilder);
            //2.3、构建自定义的seller_remark_score
            ScoreFunctionBuilder<FieldValueFactorFunctionBuilder> sellerRemarkScoreFunctionBuilder = new FieldValueFactorFunctionBuilder("seller_remark_score");
            sellerRemarkScoreFunctionBuilder.setWeight(0.1f);
            filterFunctionBuilders[2] = new FunctionScoreQueryBuilder.FilterFunctionBuilder(sellerRemarkScoreFunctionBuilder);

            FunctionScoreQueryBuilder functionScoreQueryBuilder = QueryBuilders.functionScoreQuery(boolQueryBuilder, filterFunctionBuilders)
                    .boostMode(CombineFunction.SUM)
                    .scoreMode(FunctionScoreQuery.ScoreMode.SUM);

            searchSourceBuilder.query(functionScoreQueryBuilder)
                    .sort("_score", SortOrder.DESC);
        } else {
            FunctionScoreQueryBuilder.FilterFunctionBuilder[] filterFunctionBuilders = new FunctionScoreQueryBuilder.FilterFunctionBuilder[1];
            ScoreFunctionBuilder<FieldValueFactorFunctionBuilder> pricePerManFunctionBuilder = new FieldValueFactorFunctionBuilder("price_per_man");
            pricePerManFunctionBuilder.setWeight(1);
            filterFunctionBuilders[0] = new FunctionScoreQueryBuilder.FilterFunctionBuilder(pricePerManFunctionBuilder);

            FunctionScoreQueryBuilder functionScoreQueryBuilder = QueryBuilders.functionScoreQuery(boolQueryBuilder, filterFunctionBuilders)
                    .boostMode(CombineFunction.REPLACE)
                    .scoreMode(FunctionScoreQuery.ScoreMode.SUM);
            searchSourceBuilder.query(functionScoreQueryBuilder)
                    .sort("_score", SortOrder.ASC);
        }


        //3.1 编写script_fields返回distance字段
        Map<String, Object> params = new HashMap<>(16);
        params.put("lat", longitude);
        params.put("lon", latitude);
        String lang = "expression";
        String idOrCode = "haversin(lat,lon,doc['location'].lat,doc['location'].lon)";
        Script script = new Script(ScriptType.INLINE, lang, idOrCode, params);

        //4.1 构建聚合
        TermsAggregationBuilder termsAggregationBuilder = AggregationBuilders.terms("group_by_tags").field("tags");


        //想要查询的字段
        String[] includeFields = new String[]{"id"};
        //排除的字段
        String[] excludeFields = new String[]{};

        searchSourceBuilder.scriptField("distance", script)
                .fetchSource(includeFields, excludeFields)
                .aggregation(termsAggregationBuilder);

        searchRequest.source(searchSourceBuilder);
        try {
            SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
            if (RestStatus.OK.equals(searchResponse.status())) {
                List<ShopResponse> shopResponseList = new ArrayList<>();
                SearchHits hits = searchResponse.getHits();
                SearchHit[] searchHits = hits.getHits();
                for (SearchHit hit : searchHits) {
                    //获得ES主键=source里面的id
                    String id = hit.getId();
                    Shop shop = shopService.get(Integer.valueOf(id));
                    ShopResponse shopResponse = MapperFactory.getCopyByRefMapper().mapClass(Shop.class, ShopResponse.class)
                            .registerAndMap(shop, ShopResponse.class);
                    shopResponse.setCategoryModel(shop.getCategoryModel());
                    shopResponse.setSellerModel(shop.getSellerModel());

                    //获得距离
                    Map<String, DocumentField> fields = hit.getFields();
                    DocumentField distanceField = fields.get("distance");
                    BigDecimal disValue = new BigDecimal(distanceField.getValue().toString());
                    shopResponse.setDistance(disValue.multiply(new BigDecimal(1000).setScale(0,BigDecimal.ROUND_CEILING)).intValue());

                    shopResponseList.add(shopResponse);
                }

                List<Map<String, Object>> tagsList = new ArrayList<>();
                Aggregations aggregations = searchResponse.getAggregations();
                Terms byTagsAggregation = aggregations.get("group_by_tags");
                List<? extends Terms.Bucket> buckets = byTagsAggregation.getBuckets();
                for (Terms.Bucket bucket : buckets) {
                    Map<String, Object> tagMap = new HashMap<>(16);
                    long docCount = bucket.getDocCount();
                    String tag = (String) bucket.getKey();
                    tagMap.put("tags", tag);
                    tagMap.put("num", docCount);
                    tagsList.add(tagMap);
                }

                result.put("tags", tagsList);
                result.put("shop", shopResponseList);
            }
        } catch (IOException e) {
            log.error("{}:", e.getMessage());
        }
        return result;
    }

写回答

2回答

龙虾三少

2020-11-23

不需要

0
0

龙虾三少

2020-03-11

没看懂你的问题

0
1
小耶哥
他的意思不想按照你的这种构建jsonObject 直接使用官方文档编写 我目前使用的也是官方文档, 不过老师的这种 我看着更麻烦, 可能是我太菜了 我在研究一下
2020-11-22
共1条回复

ES7+Spark 构建高匹配度搜索服务+千人千面推荐系统

ElasticSearch实现高相关性搜索,Spark MLlib实现个性化推荐

1386 学习 · 559 问题

查看课程