欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

ES操作

程序员文章站 2022-07-06 15:46:47
...

ES基本使用
导包

 <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>

一、准备启动类
二、写配置文件 application.yml

spring:
  application:
    name: hrm-es-server  #服务名
  data:
    elasticsearch:
      cluster-name: elasticsearch
      cluster-nodes: 127.0.0.1:9300 #9200是图形界面端,9300代码端

三、创建实体类 为EmpDoc做文档映

@Document(indexName = "cms", type = "user")
@Data
public class UserDoc {
    //对应文档的id
    @Id
    private Long id;
    //用户名
    @Field(type = FieldType.Keyword)
    private String username;
    //介绍  analyzer
    @Field(type = FieldType.Text, analyzer = "ik_smart", searchAnalyzer = "ik_smart")
    private String intro;
    //年龄
    @Field(type = FieldType.Integer)
    private Integer age;
    //性别
    @Field(type = FieldType.Integer)
    private Integer sex;
}

四、写一个repository

@Repository
public interface UserElasticRepository extends ElasticsearchRepository<UserDoc,Long> {
}

五、配置mapper

package cn.itsource.mapper;

import com.alibaba.fastjson.JSON;
import net.minidev.json.JSONObject;
import org.assertj.core.util.Lists;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.SearchResultMapper;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPageImpl;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;

@Component
public class HighlightResultMapper implements SearchResultMapper {

    @Override
    public <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> aClass, Pageable pageable) {
        // 记录总条数
        long totalHits = response.getHits().getTotalHits();
        // 记录列表(泛型) - 构建Aggregate使用
        List<T> list = Lists.newArrayList();
        // 获取搜索结果(真正的的记录)
        SearchHits hits = response.getHits();
        for (SearchHit hit : hits) {
            if(hits.getHits().length <= 0){
                return null;
            }
            // 将原本的JSON对象转换成Map对象
            Map<String, Object> map = hit.getSourceAsMap();
            // 获取高亮的字段Map
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            for (Map.Entry<String, HighlightField> highlightField : highlightFields.entrySet()) {
                // 获取高亮的Key
                String key = highlightField.getKey();
                // 获取高亮的Value
                HighlightField value = highlightField.getValue();
                // 实际fragments[0]就是高亮的结果,无需遍历拼接
                Text[] fragments = value.getFragments();
                StringBuilder sb = new StringBuilder();
                for (Text text : fragments) {
                    sb.append(text);
                }
                // 因为高亮的字段必然存在于Map中,就是key值
                // 可能有一种情况,就是高亮的字段是嵌套Map,也就是说在Map里面还有Map的这种情况,这里没有考虑
                map.put(key, sb.toString());
            }
            // 把Map转换成对象
            T item = JSON.parseObject(JSONObject.toJSONString(map),aClass);
            list.add(item);
        }
        // 返回的是带分页的结果
        return new AggregatedPageImpl<>(list, pageable, totalHits,response.getAggregations());
    }

}


六、Test测试


@RunWith(SpringRunner.class)
@SpringBootTest(classes = App.class)
public class ESTest {
    @Autowired
    private ElasticsearchTemplate template;

    @Autowired
    private UserElasticRepository repository;

    @Autowired
    private HighlightResultMapper resultMapper;


    /**
     * 1.创建索引库
     * 2.做文档映射
     * 3.存储文档数据
     */
    @Test
    public void testCreateIndex() {
        //创建索引
        template.createIndex(UserDoc.class);
        //创建映射
        template.putMapping(UserDoc.class);
    }


    /**
     * 批量添加数据
     *
     * @return
     */
    public List<UserDoc> createDataInBulk() {
        List<UserDoc> list = new ArrayList<>();
        UserDoc userDoc = null;
        for (int i = 1; i <= 50; i++) {
            if (i % 2 == 0) {
                userDoc = new UserDoc(Long.valueOf(i), "王小二", "我今晚打小徐" + i + "次", 12 + i, 1);
                list.add(userDoc);
            } else {
                userDoc = new UserDoc(Long.valueOf(i), "王小翠", "我今晚帮助王小二打小徐" + i + "次", 10 + i, 0);
                list.add(userDoc);
            }
        }
        return list;
    }


    /**
     * 添加文档数据
     */
    @Test
    public void testAddDocumentData() {
        /* UserDoc userDoc = new UserDoc(1L, "王甜甜", "我是一个可爱的女生", 18, 0);*/
        List<UserDoc> userDoc = createDataInBulk();
        repository.saveAll(userDoc);
        System.out.println("操作成功.....");
    }

    /**
     * 修改文档数据
     */
    @Test
    public void testUpdateDocumentData() {
        //创建一个userDoc对象
        UserDoc userDoc = new UserDoc(1L, "李建", "我是一个可爱的男孩", 20, 1);
        //将userDoc对象添加到文档数据库中
        repository.save(userDoc);
        System.out.println("操作成功.....");
    }

    /**
     * 查询文档数据
     */
    @Test
    public void testSearchDocumentData() {
        //根据id查询文档数据
        Optional<UserDoc> optional = repository.findById(1L);
        //获取查询出来的数据
        UserDoc userDoc = null;
        try {
            userDoc = optional.get();
            System.out.println(userDoc);
        } catch (NoSuchElementException e) {
            System.out.println("数据为空");
            e.printStackTrace();
        }

    }

    /**
     * 删除文档数据
     */
    @Test
    public void testDeleteDocumentData() {
        repository.deleteById(1L);
        System.out.println("删除成功...");
    }

    /**
     * 高级文档查询
     * 查询 username 中叫 “ 王小翠 ”的人,简介包含:“今晚”,年龄在 18 -  35之间的  ,性别为 女  按照年龄进行降序排序,显示第2页的数据,每页展示5条数据,
     */
    @Test
    public void testAdvancedDocumentQuery() {
        //构建查询对象
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        //分页   显示第2页的数据,每页展示5条数据,
        builder.withPageable(PageRequest.of(0, 5));
        //排序   按照年龄进行降序排序
        builder.withSort(SortBuilders.fieldSort("age").order(SortOrder.DESC));
        //查询条件
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        //标准查询  查询 username 中叫 “ 王小二 ”的人
        boolQueryBuilder.must(QueryBuilders.termQuery("username", "王小二"));
        //过滤查询  简介包含:“今晚”,年龄在 18 -  35之间的  ,性别为 女
        boolQueryBuilder.filter(QueryBuilders.rangeQuery("age").gte(18).lte(35))
                .filter(QueryBuilders.termQuery("sex", 1))
                .filter(QueryBuilders.matchQuery("intro", "今晚"));
        //添加到查询语句中
        builder.withQuery(boolQueryBuilder);
        //构建一个查询对象
        NativeSearchQuery build = builder.build();
        //执行查询
        Page<UserDoc> page = repository.search(build);
        //处理结果
        System.out.println("命中总条数:" + page.getTotalElements());
        System.out.println("命中总页数:" + page.getTotalPages());
        //查询结果
        page.forEach(System.out::println);
    }

    /**
     * 高亮查询
     */
    @Test
    public void testHighlightQuery() {
        //构建查询对象
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        //分页   显示第2页的数据,每页展示5条数据,
        builder.withPageable(PageRequest.of(0, 5));
        //排序   按照年龄进行降序排序
        builder.withSort(SortBuilders.fieldSort("age").order(SortOrder.DESC));
        //查询条件
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        //标准查询  查询 username 中叫 “ 王小二 ”的人
        boolQueryBuilder.must(QueryBuilders.termQuery("username", "王小翠"));
        //过滤查询  简介包含:“今晚”,年龄在 18 -  35之间的  ,性别为 女
        boolQueryBuilder.filter(QueryBuilders.rangeQuery("age").gte(18).lte(35))
                .filter(QueryBuilders.termQuery("sex", 0))
                .filter(QueryBuilders.matchQuery("intro", "帮助"));
        //添加到查询语句中
        builder.withQuery(boolQueryBuilder);
        //构建一个查询对象
        NativeSearchQuery build = builder.build();
        //执行查询
        //设置高亮显示===========================================
        HighlightBuilder.Field field = new HighlightBuilder.Field("intro").preTags("<font style='color:red'>").postTags("</font>");
        builder.withHighlightFields(field);
        //执行查询
        AggregatedPage<UserDoc> userDocs = template.queryForPage(build, UserDoc.class, resultMapper);
        //处理结果
        System.out.println("命中总条数:" + userDocs.getTotalElements());
        System.out.println("命中总页数:" + userDocs.getTotalPages());
        //查询结果
        userDocs.forEach(System.out::println);
    }


    /**
     * 聚合查询
     */
    @Test
    public void testAggregationQuery() {
        //构建查询对象
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        //分页   显示第2页的数据,每页展示5条数据,
        builder.withPageable(PageRequest.of(0, 5));
        //排序   按照年龄进行降序排序
        builder.withSort(SortBuilders.fieldSort("age").order(SortOrder.DESC));
        //查询条件
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        //标准查询  查询 username 中叫 “ 王小二 ”的人
        boolQueryBuilder.must(QueryBuilders.termQuery("username", "王小翠"));
        //过滤查询  简介包含:“今晚”,年龄在 18 -  35之间的  ,性别为 女
        boolQueryBuilder.filter(QueryBuilders.rangeQuery("age").gte(18).lte(35))
                .filter(QueryBuilders.termQuery("sex", 0))
                .filter(QueryBuilders.matchQuery("intro", "帮助"));
        //添加到查询语句中
        builder.withQuery(boolQueryBuilder);
        //构建一个查询对象
        NativeSearchQuery build = builder.build();
        //执行查询
        //聚合查询
        TermsAggregationBuilder tenantAgg = AggregationBuilders.terms("sex").field("sex")
                .order(Terms.Order.count(false)).size(10);  //按照count倒排
        builder.addAggregation(tenantAgg);
        AggregatedPage<UserDoc> userDocs = template.queryForPage(builder.build(), UserDoc.class, resultMapper);
        //处理结果
        System.out.println("命中总条数:" + userDocs.getTotalElements());
        System.out.println("命中总页数:" + userDocs.getTotalPages());
        //查询结果
        userDocs.forEach(System.out::println);
        //获取聚合结果
        LongTerms terms = (LongTerms) userDocs.getAggregation("sex");
        List<LongTerms.Bucket> buckets = terms.getBuckets();
        for (LongTerms.Bucket bucket : buckets) {
            if (1 == (Long) bucket.getKey()) {
                System.out.println("男生有:" + bucket.getDocCount());
            } else {
                System.out.println("女生有:" + bucket.getDocCount());
            }
        }
        //把机构名字聚合,搜集成字符串里集合
//        List<String> collect = buckets.stream().map(bucket -> bucket.getKeyAsString()).collect(Collectors.toList());

    }


}

七、web.controller操作



@RestController
@RequestMapping("/search")
public class SearchCourseController {

    @Autowired
    private SearchElasticRepository repository;

    @Autowired
    private ElasticsearchTemplate template;

    @Autowired
    private HighlightResultMapper highlightResultMapper;

    /**
     * 添加全文搜索的信息和展示字段
     *
     * @param courseQuery
     * @return
     */

    @RequestMapping(value = "/course/queryCourses", method = RequestMethod.POST)
    public AjaxResult queryCourses(@RequestBody CourseQuery courseQuery) {
        //构建查询对象
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        BoolQueryBuilder boolQueryBuilder = getQueryBuilder(courseQuery, builder);
        builder.withQuery(boolQueryBuilder);
        //给对应的字段设置高亮========================================
        HighlightBuilder.Field field = new HighlightBuilder.Field("name").preTags("<font style='color:red'>").postTags("</font>");
        builder.withHighlightFields(field);
        //设置聚合==================================================
        TermsAggregationBuilder termsAggregationBuilder = AggregationBuilders.terms("tenantName").field("tenantName")
                .order(Terms.Order.count(false)).size(10);
        builder.addAggregation(termsAggregationBuilder);
        //构建一个查询对象
        NativeSearchQuery build = builder.build();
        //执行查询
        AggregatedPage<SearchDoc> page = template.queryForPage(build, SearchDoc.class, highlightResultMapper);
        StringTerms terms = (StringTerms) page.getAggregation("tenantName");
        List<SearchVo> list = new ArrayList<>();
        terms.getBuckets().stream().map(bucket -> list.add(new SearchVo(bucket.getDocCount(), bucket.getKeyAsString()))).collect(Collectors.toList());
        //处理结果
        return AjaxResult.me().setResultObj(new SearchDocQuery(page.getTotalPages(), page.getContent(), list));
    }

    /**
     * 构建查询对象
     *
     * @param courseQuery
     * @param builder
     * @return
     */
    private BoolQueryBuilder getQueryBuilder(CourseQuery courseQuery, NativeSearchQueryBuilder builder) {
        //分页=====================================================
        builder.withPageable(PageRequest.of(courseQuery.getPage() - 1, courseQuery.getRows()));
        //排序=====================================================
        builder.withSort(SortBuilders.fieldSort(courseSort(courseQuery))
                .order("desc".equalsIgnoreCase(courseQuery.getSortType()) ? SortOrder.DESC : SortOrder.ASC));
        //条件查询==================================================
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        if (StringUtils.hasLength(courseQuery.getKeyword())) {
            String keyword = courseQuery.getKeyword();
            boolQueryBuilder.must(QueryBuilders.termQuery("name", keyword));
        }
        if (!(courseQuery.getCourseTypeId() == null)) {
            Long courseTypeId = courseQuery.getCourseTypeId();
            boolQueryBuilder.filter(QueryBuilders.termQuery("courseTypeId", courseTypeId));
        }
        if (!(courseQuery.getPriceMin() == null)) {
            Float priceMin = courseQuery.getPriceMin();
            boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").gte(priceMin));
        }
        if (!(courseQuery.getPriceMax() == null)) {
            Float priceMax = courseQuery.getPriceMax();
            boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").lte(priceMax));
        }

        if (StringUtils.hasLength(courseQuery.getTenantName())) {
            String tenantName = courseQuery.getTenantName();
            boolQueryBuilder.filter(QueryBuilders.termQuery("tenantName", tenantName));
        }
        return boolQueryBuilder;
    }

    /**
     * 按照什么字段排序
     */
    public String courseSort(CourseQuery courseQuery) {
        String sortField = courseQuery.getSortField();
        if (StringUtils.hasLength(sortField)) {
            switch (sortField) {
                case "xp":
                    return "onlinkDate";
                case "pl":
                    return "commentCount";
                case "jg":
                    return "price";
                case "rq":
                    return "viewCount";
            }
        }
        return "saleCount";
    }


    /**
     * 添加全文搜索的信息和展示字段
     *
     * @param searchDoc
     * @return
     */
    @PreAuthorize("hasAuthority('es:online')")
    @RequestMapping("/addToCourseResearchAll")
    public AjaxResult addToCourseResearchAll(@RequestBody SearchDoc searchDoc) {
        repository.save(searchDoc);
        return AjaxResult.me();
    }
}


相关标签: java