10-Spring boot nosql solr

Apache Solr是一個(gè)搜索引擎。Spring boot為Solr client version5 提供了起步配置,spring-boot-starter-data-solr喂柒。添加Spring boot起步maven依賴:

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

單獨(dú)使用時(shí)maven配置:

<dependency>
  <groupId>org.apache.solr</groupId>
  <artifactId>solr-solrj</artifactId>
  <version>7.5.0</version>
</dependency>
配置SolrClient

可以使用XML和注解的方式配置SolrClient。

XML配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:solr="http://www.springframework.org/schema/data/solr"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/data/solr
    http://www.springframework.org/schema/data/solr/spring-solr.xsd">

  <solr:solr-client id="solrClient" url="http://locahost:8983/solr" />
<!-- 配置 load balance solr client-->
<solr:solr-client id="solrClient" url="http://locahost:8983/solr,http://localhost:8984/solr" />
<!-- 使用內(nèi)置Solr-->
<solr:embedded-solr-server id="solrClient" solrHome="classpath:com/acme/solr" />
</beans>
Java注解配置

使用注解配置Solr repositories。如下:

@Configuration
@EnableSolrRepositories
public class SolrConfiguration {

    @Bean
    public  SolrClient getSolrClient(){
        
        HttpSolrClient client = new HttpSolrClient.
                Builder("http://192.168.152.133:8983/solr").build();
        return client;
    }
    
    @Bean
    public SolrOperations getSolrOperations(SolrClient solrClient){
        
        return new SolrTemplate(solrClient);
    }
}
定義實(shí)體

在配置通過注解@EnableSolrRepositories已經(jīng)啟用solrRepository紊扬,使用SolrDocument注解配置Solr entity

@SolrDocument(collection = "productCl")
public class Product {

    private @Id @Indexed String productId;
    
    private @Indexed String name;
    
    private @Indexed String categories;
    
    private @Indexed Float price;

    private @Indexed List<String> authors;
    
    private @Indexed boolean available;
        //setter getter 省略
}
創(chuàng)建SolrRepository

SolrCrudRepository繼承自SolrRepository,SolrRepository又繼承自PagingAndSortingRepository唉擂,自定義的mySolrRepository需繼承自SolrCrudRepository餐屎,通過命名的方式和@Query注解的方式實(shí)現(xiàn)查詢接口。

@Repository
public interface MySolrRepository extends SolrCrudRepository<Product, String>{

    
    public List<Product> findByNameAndAvailable(String name,boolean available);
    
    @Query(fields={"name","categories","productId"},defaultOperator=Operator.AND)
    public List<Product> findByNameIn(String name);
    
    
    public List<Product> findByName(String name,Pageable page);
}

在Service中使用調(diào)用SolrRepository方法時(shí)玩祟,可以使用事物支持腹缩。如下:

    @Transactional
    public Product save(Product product){
        
        Product pr = repository.save(product);
        return pr;
    }
Document映射

完成數(shù)據(jù)庫中對(duì)象到實(shí)體之間的映射要完成兩個(gè)步驟:
1,使用實(shí)體暴露的初始化函數(shù)創(chuàng)建實(shí)體實(shí)例
2空扎,填充實(shí)例暴露的所有屬性藏鹊;

對(duì)象的創(chuàng)建

Spring data會(huì)自動(dòng)檢測(cè)持久化對(duì)象的構(gòu)造函數(shù)來實(shí)例對(duì)象實(shí)例,基于以下的策略:
1转锈,如果存在無參構(gòu)造函數(shù)盘寡,就會(huì)使用這個(gè),并忽略其他構(gòu)造函數(shù)撮慨;
2竿痰,如果只有一個(gè)帶參構(gòu)造函數(shù),則使用這個(gè)砌溺;
3影涉,如果有多個(gè)帶參構(gòu)造函數(shù),需要使用@PersistenceConstructor標(biāo)識(shí)哪個(gè)可以被Spring data使用规伐。
為了避免使用反射的開銷常潮,Spring data默認(rèn)會(huì)在運(yùn)行期使用工廠類創(chuàng)建對(duì)象實(shí)例,直接調(diào)用實(shí)體類的構(gòu)造器楷力,但是這樣的實(shí)體類需滿足如下條件:
1喊式,不能是被private修飾的類
2,不能包含靜態(tài)的內(nèi)部類
3萧朝,不能是CGLib代理類
4岔留,被Spring data使用的構(gòu)造函數(shù)必須事public類型
如果實(shí)體類包含以上其中一點(diǎn),Spring data就會(huì)使用反射創(chuàng)建實(shí)體實(shí)例检柬。

屬性填充

一旦創(chuàng)建了實(shí)體的實(shí)例献联,Spring Data就會(huì)填充該類的所有剩余持久屬性竖配。 除非已經(jīng)由實(shí)體的構(gòu)造函數(shù)填充(即通過其構(gòu)造函數(shù)參數(shù)列表使用),否則將首先填充identifier屬性以允許循環(huán)對(duì)象引用的解析里逆。之后进胯,在實(shí)體實(shí)例上設(shè)置尚未由構(gòu)造函數(shù)填充的所有non-transient屬性,這些屬性的填充按照如下的策略:
1原押,如果屬性是不可變的但是公開了一個(gè)write方法胁镐,使用write來創(chuàng)建一個(gè)具有新屬性值的新實(shí)體實(shí)例。
2诸衔,如果屬性提供了setter或則getter方法盯漂,將會(huì)調(diào)用setter方法。
3笨农,默認(rèn)情況下就缆,直接設(shè)置屬性值。

MappingSolrConverter

MappingSolrConverter允許你為SolrDocument和SolrInputDocument注冊(cè)自定義的轉(zhuǎn)化器谒亦,轉(zhuǎn)換器完全和DocumentObjectBinder兼容竭宰,使用@Indexed注解的屬性需要使用readonly=true以防止寫入Solr。添加CustomConversions

    @Bean
    public SolrCustomConversions getConversion(){
        
        SolrCustomConversions conversions = new SolrCustomConversions(new ArrayList<>());
        return conversions;
    }

添加轉(zhuǎn)換器

    @Bean
    public SolrConverter getSolrConverter(){
        
        SimpleSolrMappingContext context = new SimpleSolrMappingContext();
        MappingSolrConverter converter = new MappingSolrConverter(context);
        converter.setCustomConversions(getConversion());
        return converter;
    }

在SolrTemplate中添加Converter:

    @Bean
    public SolrOperations getSolrOperations(SolrClient solrClient){
        
        SolrTemplate tmp = new SolrTemplate(solrClient);
        tmp.setSolrConverter(getSolrConverter());
        return tmp;
    }

Solr操作的其他支持

使用SolrDocument注解

指定實(shí)體類在Solr中對(duì)應(yīng)的集合名稱,可以使用靜態(tài)值或則SpEl表達(dá)式:

//直接指定值
@SolrDocument(collection = "techproducts")
class StaticCollectionName { ... }

//使用Spel表達(dá)式,使用引用值
@SolrDocument(collection = "#{@someBean.getCollectionName()}")
class DynamicCollectionName { ... }
局部更新

使用PartialUpdate實(shí)現(xiàn)局部更新操作。例如:

public void PatialUpdateTest(Product product){
        
  PartialUpdate update = new PartialUpdate("productId", "123");
  update.setValueOfField("name", "newValue");
  operations.saveBean("product", update);
}
分片支持查詢

SolrRepository不能實(shí)現(xiàn)分片查詢,但是可以使用SolrTemplate實(shí)現(xiàn)恢暖。

    public void facetSearchTest(){
        
        FacetQuery query = new SimpleFacetQuery(new 
                Criteria(Criteria.WILDCARD).expression(Criteria.WILDCARD))
                .setFacetOptions(new FacetOptions().addFacetOnField("name").setFacetLimit(5));
        FacetPage<Product> page = operations.queryForFacetPage("productCl", query, Product.class);
        System.out.println(page);
    }
Range Faceting

在FacetOptions上設(shè)置查詢范圍,通過SolrTemplate查詢涉兽。

public FacetPage<Product> facetSearchByRange(){
        
        FacetOptions options = new FacetOptions()
            .addFacetByRange(new FacetOptions.
                    FieldWithNumericRangeParameters("price", 5, 20, 5).
                    setHardEnd(true).
                    setInclude(FacetRangeInclude.ALL)
                    );
        options.setFacetMinCount(0);
        FacetQuery query = new SimpleFacetQuery(new 
                SimpleStringCriteria("*:*")).setFacetOptions(options);
        FacetPage<Product> page = this.operations.queryForFacetPage("productCl", query, Product.class);
        return page;
    }

兩種設(shè)置范圍查詢的實(shí)現(xiàn):
1深碱,數(shù)值類型的范圍:使用數(shù)值類型的范圍查詢,實(shí)現(xiàn)類org.springframework.data.solr.core.query.FacetOptions.FieldWithNumericRangeParameters棺蛛,參數(shù)是start value怔蚌,end value,和一個(gè)gap旁赊。
2桦踊,日期范圍:使用org.springframework.data.solr.core.query.FacetOptions.FieldWithDateRangeParameters類,參數(shù)是開始日期(start date)终畅,結(jié)束日期(end date)和一個(gè)gap(間隔)籍胯。可以使用org.apache.solr.util.DateMathParser來定義gap离福。
另外也可以使用org.springframework.data.solr.core.query.FacetOptions.FieldWithRangeParameters來配置范圍參數(shù)杖狼,相關(guān)配置如下:
Hard end:setHardEnd(Boolean):定義是否應(yīng)該結(jié)束最后一個(gè)范圍,即使結(jié)束不滿足條件妖爷。
Include:setInclude(org.apache.solr.common.params.FacetParams.FacetRangeInclude):定義邊界的處理方式蝶涩。
Other:setOther(org.apache.solr.common.params.FacetParams.FacetRangeOther):其他選項(xiàng)定義。

Terms 支持

使用SolrTemplate可以實(shí)現(xiàn)Terms查詢,但是不能使用SolrRepository绿聘,返回TermPage對(duì)象嗽上。例如下:

    public TermsPage findByTerms(){
        
        TermsQuery query = SimpleTermsQuery.queryBuilder().fields("name").build();
        TermsPage page = operations.queryForTermsPage("productCl", query);
        return page;
    }
查詢結(jié)果分組

查詢結(jié)果分組也不能使用SolrRepository實(shí)現(xiàn),但是可以使用SolrTemplate熄攘,返回?cái)?shù)據(jù)為GroupPage兽愤。如下:

    public GroupPage<Product> findByGroup(){
        
        Field field = new SimpleField("price");
        Function func = ExistsFunction.exists("categories");
        Query query = new SimpleQuery("available:true");
        
        SimpleQuery groupQuery = new SimpleQuery(new SimpleStringCriteria("*:*"));
        GroupOptions groupOptions = new GroupOptions().addGroupByField(field)
                .addGroupByFunction(func)
                .addGroupByQuery(query);
        groupQuery.setGroupOptions(groupOptions);
        
        GroupPage<Product> page = operations.queryForGroupPage("productCl", query, Product.class);
        
        GroupResult<Product> fieldGroupResult = page.getGroupResult(field);
        GroupResult<Product> funcGroupResult = page.getGroupResult(func);
        GroupResult<Product> queryGroupResult = page.getGroupResult(query);
        
        return page;
    }
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市鲜屏,隨后出現(xiàn)的幾起案子烹看,更是在濱河造成了極大的恐慌,老刑警劉巖洛史,帶你破解...
    沈念sama閱讀 211,639評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件惯殊,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡也殖,警方通過查閱死者的電腦和手機(jī)土思,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來忆嗜,“玉大人己儒,你說我怎么就攤上這事±粒” “怎么了闪湾?”我有些...
    開封第一講書人閱讀 157,221評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)绩卤。 經(jīng)常有香客問我途样,道長(zhǎng),這世上最難降的妖魔是什么濒憋? 我笑而不...
    開封第一講書人閱讀 56,474評(píng)論 1 283
  • 正文 為了忘掉前任何暇,我火速辦了婚禮,結(jié)果婚禮上凛驮,老公的妹妹穿的比我還像新娘裆站。我一直安慰自己,他們只是感情好黔夭,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,570評(píng)論 6 386
  • 文/花漫 我一把揭開白布宏胯。 她就那樣靜靜地躺著,像睡著了一般本姥。 火紅的嫁衣襯著肌膚如雪胳嘲。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,816評(píng)論 1 290
  • 那天扣草,我揣著相機(jī)與錄音了牛,去河邊找鬼颜屠。 笑死,一個(gè)胖子當(dāng)著我的面吹牛鹰祸,可吹牛的內(nèi)容都是我干的甫窟。 我是一名探鬼主播,決...
    沈念sama閱讀 38,957評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼蛙婴,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼粗井!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起街图,我...
    開封第一講書人閱讀 37,718評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤浇衬,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后餐济,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體耘擂,經(jīng)...
    沈念sama閱讀 44,176評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,511評(píng)論 2 327
  • 正文 我和宋清朗相戀三年絮姆,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了醉冤。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,646評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡篙悯,死狀恐怖蚁阳,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情鸽照,我是刑警寧澤螺捐,帶...
    沈念sama閱讀 34,322評(píng)論 4 330
  • 正文 年R本政府宣布,位于F島的核電站矮燎,受9級(jí)特大地震影響定血,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜漏峰,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,934評(píng)論 3 313
  • 文/蒙蒙 一糠悼、第九天 我趴在偏房一處隱蔽的房頂上張望届榄。 院中可真熱鬧浅乔,春花似錦、人聲如沸铝条。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,755評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽班缰。三九已至贤壁,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間埠忘,已是汗流浹背脾拆。 一陣腳步聲響...
    開封第一講書人閱讀 31,987評(píng)論 1 266
  • 我被黑心中介騙來泰國打工馒索, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人名船。 一個(gè)月前我還...
    沈念sama閱讀 46,358評(píng)論 2 360
  • 正文 我出身青樓绰上,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國和親渠驼。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蜈块,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,514評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,773評(píng)論 6 342
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)迷扇,斷路器百揭,智...
    卡卡羅2017閱讀 134,633評(píng)論 18 139
  • 這一次,累蜓席,無奈器一,有心無力,恨鐵不成鋼瓮床,不知道還能干啥盹舞,算了,走一步算一步吧
    夢(mèng)想多遠(yuǎn)行多遠(yuǎn)閱讀 192評(píng)論 2 0
  • 如果說他的命運(yùn)是那破舊的花架隘庄,那么因?yàn)樗膱?jiān)強(qiáng)意志踢步,變得繁花似錦光艷奪人; 如果說他的命運(yùn)是那漆黑的夜空丑掺,那么因?yàn)?..
    Aurevoir47閱讀 194評(píng)論 0 0
  • 雨夜一盞窗外燈获印,臨空靜聽蛙聲音。 烏云密布蔽明月街州,蒙雷炸破斷乾坤兼丰。 大別山下數(shù)好漢,木易沖鋒算一人唆缴。 仰天狂笑夢(mèng)中...
    風(fēng)中的白楊閱讀 146評(píng)論 0 1