全文檢索的應(yīng)用越來越廣泛郭宝,幾乎成了互聯(lián)網(wǎng)應(yīng)用的標(biāo)配辞槐,商品搜索、日志分析粘室、歷史數(shù)據(jù)歸檔等等榄檬,各種場(chǎng)景都會(huì)涉及到大批量的數(shù)據(jù),在全文檢索方面衔统,方案無外乎Lucene鹿榜、Solr、Elasticsearch三種應(yīng)用的較為廣泛锦爵。es舱殿、solr的底層都依托于Lucene,但es比solr學(xué)習(xí)成本更低险掀,由于其提供的RESTful API簡(jiǎn)單快捷沪袭,對(duì)互聯(lián)網(wǎng)應(yīng)用開發(fā)而言更是如虎添翼。
下面結(jié)合以實(shí)際案例樟氢,通過Java API的形式操作es數(shù)據(jù)集冈绊。
框架選型基礎(chǔ)是Spring Boot + Spring-data-elasticsearch + elasticsearch。
使用ElasticsearchRepository的形式來連接埠啃、維護(hù)ES數(shù)據(jù)集死宣,ElasticsearchRepository中提供了簡(jiǎn)單的操作索引數(shù)據(jù)的方法集合,繼承自ElasticsearchCrudRepository霸妹,涵蓋了CRUD十电、排序、分頁等常見的基本操作功能。
@NoRepositoryBean ?
public interface ElasticsearchRepository extends ElasticsearchCrudRepository { ?
? ? S index(S var1); ?
? ?Iterable search(QueryBuilder var1); ?
? ?Page search(QueryBuilder var1, Pageable var2); ?
? ?Page search(SearchQuery var1); ?
? ?Page searchSimilar(T var1, String[] var2, Pageable var3); ?
? ?void refresh(); ?
? ?Class getEntityClass(); ?
} ?
編寫自己的Resository操作類
public interface ArticleSearchRepository extends ElasticsearchRepository{
? ?List findByAbstractsAndContent(String abstracts, String content);
}
其中Article為是與elasticsearch連接的實(shí)體類鹃骂,類似于PO的概念台盯,其中指定的索引名稱、類型名稱畏线、及分片静盅、副本數(shù)量等要素。
@Data
@Document(indexName = "article_index", type = "article", shards = 5, replicas = 1, indexStoreType = "fs", refreshInterval = "-1")
public class Article implements Serializable {
? ?/**
? ? * serialVersionUID:
? ? *
? ? * @since JDK 1.6
? ? */
? ?private static final long serialVersionUID = 1L;
? ?@Id
? ?private Long id;
? ?/** 標(biāo)題 */
? ?private String title;
? ?/** 摘要 */
? ?private String abstracts;
? ?/** 內(nèi)容 */
? ?private String content;
? ?/** 發(fā)表時(shí)間 */
? ?@Field(format = DateFormat.date_time, index = FieldIndex.no, store = true, type = FieldType.Object)
? ?private Date postTime;
? ?/** 點(diǎn)擊率 */
? ?private Long clickCount;
}
我們需要定義域的實(shí)體和一個(gè)Spring data的基本的CRUD支持庫類寝殴。用id注釋定義標(biāo)識(shí)符字段蒿叠,如果你沒有指定ID字段,Elasticsearch不能索引你的文件蚣常。同時(shí)需要指定索引名稱類型市咽,@Document注解也有助于我們?cè)O(shè)置分片和副本數(shù)量。
接口類
public interface ArticleService {
? ?/**
? ? * saveArticle: 寫入
? ? *
? ? * @author guooo Date:2017年9月27日下午3:20:06
? ? * @param article
? ? * @return
? ? * @since JDK 1.6
? ? */
? ?long saveArticle(Article article);
? ?/**
? ? * deleteArticle: 刪除抵蚊,并未真正刪除施绎,只是查詢不到
? ? *
? ? * @author guooo Date:2017年9月27日下午3:20:08
? ? * @param id
? ? * @since JDK 1.6
? ? */
? ?void deleteArticle(long id);
? ?/**
? ? * findArticle:
? ? *
? ? * @author guooo Date:2017年9月27日下午3:20:10
? ? * @param id
? ? * @return
? ? * @since JDK 1.6
? ? */
? ?Article findArticle(long id);
? ?/**
? ? * findArticlePageable:
? ? *
? ? * @author guooo Date:2017年9月27日下午3:20:13
? ? * @return
? ? * @since JDK 1.6
? ? */
? ?List findArticlePageable();
? ?/**
? ? * findArticleAll:
? ? *
? ? * @author guooo Date:2017年9月27日下午3:20:15
? ? * @return
? ? * @since JDK 1.6
? ? */
? ?List findArticleAll();
? ?/**
? ? * findArticleSort:
? ? *
? ? * @author guooo Date:2017年9月27日下午3:20:18
? ? * @return
? ? * @since JDK 1.6
? ? */
? ?List findArticleSort();
? ?/**
? ? * search:
? ? *
? ? * @author guooo Date:2017年9月27日下午3:20:22
? ? * @param content
? ? * @return
? ? * @since JDK 1.6
? ? */
? ?List search(String content);
? ?/**
? ? * update: es沒有修改操作,結(jié)合save操作完成
? ? *
? ? * @author guooo Date:2017年9月27日下午3:20:25
? ? * @param id
? ? * @return
? ? * @since JDK 1.6
? ? */
? ?long update(long id);
}
接口實(shí)現(xiàn)
@Service
public class ArticleServiceImpl implements ArticleService {
? ?final int page = 0;
? ?final int size = 10;
? ?/* 搜索模式 */
? ?String SCORE_MODE_SUM = "sum"; // 權(quán)重分求和模式
? ?Float MIN_SCORE = 10.0F; // 由于無相關(guān)性的分值默認(rèn)為 1 贞绳,設(shè)置權(quán)重分最小值為 10
? ?Pageable pageable = new PageRequest(page, size);
? ?@Autowired
? ?ArticleSearchRepository repository;
? ?@Override
? ?public long saveArticle(Article article) {
? ? ? ?Article result = repository.save(article);
? ? ? ?return result.getId();
? ?}
? ?@Override
? ?public void deleteArticle(long id) {
? ? ? ?repository.delete(id);
? ?}
? ?@Override
? ?public Article findArticle(long id) {
? ? ? ?return repository.findOne(id);
? ?}
? ?@Override
? ?public List findArticlePageable() {
? ? ? ?return repository.findAll(pageable).getContent();
? ?}
? ?@Override
? ?public List findArticleAll() {
? ? ? ?Iterable iterables = repository.findAll();
? ? ? ?List articles = new ArrayList<>();
? ? ? ?for (Article article : iterables) {
? ? ? ? ? ?articles.add(article);
? ? ? ?}
? ? ? ?return articles;
? ?}
? ?@Override
? ?public List findArticleSort() {
? ? ? ?List orders = new ArrayList<>();
? ? ? ?Order order = new Order(Direction.ASC, "clickCount");
? ? ? ?orders.add(order);
? ? ? ?Sort sort = new Sort(orders);
? ? ? ?Iterable iterables = repository.findAll(sort);
? ? ? ?List articles = new ArrayList<>();
? ? ? ?for (Article article : iterables) {
? ? ? ? ? ?articles.add(article);
? ? ? ?}
? ? ? ?return articles;
? ?}
? ?@Override
? ?public List search(String content) {
? ? ? ?return repository.findByAbstractsAndContent(content, content);
? ?}
? ?@Override
? ?public long update(long id) {
? ? ? ?Article article = repository.findOne(id);
? ? ? ?article.setTitle("test");
? ? ? ?Article retun = repository.save(article);
? ? ? ?System.out.println(retun.getId()+"更新的數(shù)據(jù)");
? ? ? ?return retun.getId();
? ?}
}
是不是與JPA谷醉、hibernate操作數(shù)據(jù)集的手法很類似?
controller方法類:
@RestController
@RequestMapping(value = "/article")
public class APIArticleController {
? ?@Autowired
? ?ArticleService articleService;
? ?@RequestMapping(value = "save", method = RequestMethod.POST)
? ?public long save() {
? ? ? ?for (int i = 10000; i < 12000; i++) {
? ? ? ? ? ?Article article = new Article();
? ? ? ? ? ?article.setClickCount(Long.valueOf(i + RandomUtils.nextInt(23, i)));
? ? ? ? ? ?article.setAbstracts("我的一個(gè)測(cè)試" + i);
? ? ? ? ? ?article.setContent(i + "這是第一個(gè)測(cè)試的內(nèi)容@spring-data-elasticsearch");
? ? ? ? ? ?article.setPostTime(new Date());
? ? ? ? ? ?article.setId(Long.valueOf(RandomUtils.nextLong(i, i)));
? ? ? ? ? ?long _id = articleService.saveArticle(article);
? ? ? ? ? ?System.out.println(_id);
? ? ? ?}
? ? ? ?return 23;
? ?}
? ?@RequestMapping(value = "delete", method = RequestMethod.POST)
? ?public void deleteArticle(long id) {
? ? ? ?articleService.deleteArticle(id);
? ?}
? ?@RequestMapping(value = "findOne", method = RequestMethod.POST)
? ?public Article findArticle(long id) {
? ? ? ?return articleService.findArticle(id);
? ?}
? ?@RequestMapping(value = "findArticlePageable", method = RequestMethod.POST)
? ?public List findArticlePageable() {
? ? ? ?return articleService.findArticlePageable();
? ?}
? ?@RequestMapping(value = "findArticleAll", method = RequestMethod.POST)
? ?public List findArticleAll() {
? ? ? ?return articleService.findArticleAll();
? ?}
? ?@RequestMapping(value = "findArticleSort", method = RequestMethod.POST)
? ?public List findArticleSort() {
? ? ? ?return articleService.findArticleSort();
? ?}
? ?@RequestMapping(value = "search", method = RequestMethod.POST)
? ?public List search(String content) {
? ? ? ?return articleService.search(content);
? ?}
? ?@RequestMapping(value = "update", method = RequestMethod.POST)
? ?public long update(long id) {
? ? ? ?return articleService.update(id);
? ?}
}
Spring Boot的啟動(dòng)類及配置項(xiàng)冈闭,這里略過俱尼,項(xiàng)目啟動(dòng)后,可能過controller暴露出來的方法進(jìn)行Article數(shù)據(jù)索引的CRUD操作萎攒。
擴(kuò)展閱讀:
Spring Boot + Elasticsearch 實(shí)現(xiàn)索引的日常維護(hù)
Spring Boot + Elasticsearch 實(shí)現(xiàn)索引批量寫入
Nginx+Lua+MySQL/Redis實(shí)現(xiàn)高性能動(dòng)態(tài)網(wǎng)頁展現(xiàn)
Nginx+Lua+Redis實(shí)現(xiàn)高性能緩存數(shù)據(jù)讀取