網(wǎng)站怎么做下載連接/百度長(zhǎng)尾關(guān)鍵詞挖掘
Neo4j的全文索引是基于Lucene實(shí)現(xiàn)的,但是Lucene默認(rèn)情況下只提供了基于英文的分詞器,下篇文章我們?cè)谟懻撝形姆衷~器(IK)的引用,本篇默認(rèn)基于英文分詞來(lái)做。我們前邊文章就舉例說(shuō)明過(guò),比如我要搜索蘋(píng)果公司?首先我們要做的第一步在各個(gè)詞條上創(chuàng)建全文索引,第二步我們根據(jù)蘋(píng)果公司進(jìn)行全文檢索,把匹配度高的按順序輸出。下邊我們一步步講解怎么做。
# Neo4j的全文索引采用Lucene,能夠?qū)eo4j中string類型的屬性建立全文索引。- 1. 能夠同時(shí)為node和relationship的屬性建立索引。而neo4j內(nèi)嵌的索引僅能夠?qū)ode的屬性建立索引。
- 2. 至于字符串如何被切分和索引,取決于為lucene配置的analyzer。支持自定義Analyzer,包括lucene中沒(méi)有提供的。
- 3. 能夠用lucene查詢語(yǔ)句進(jìn)行查詢;
- 4. 能夠返回相似度score;
- 5. 能夠隨著節(jié)點(diǎn)和關(guān)系的添加、移除、修改進(jìn)行自動(dòng)的更新;
- 6. 自動(dòng)檢查一致性,如果有不一致的問(wèn)題自動(dòng)重建;
- 7. 在單個(gè)索引中,能夠支持任意數(shù)目的文檔;
- 8. 創(chuàng)建、刪除、更新都是事務(wù)的,能夠在集群中自動(dòng)進(jìn)行副本;
- 9. 能夠通過(guò)cypher語(yǔ)句訪問(wèn).
- 10. 能夠配置為滿足最終一致性。即,索引更新在提交路徑中被移除,轉(zhuǎn)為后臺(tái)線程。利用此特性,對(duì)于性能要求高的場(chǎng)景,能夠消除主要的寫(xiě)瓶頸。# 相比于Neo4j內(nèi)嵌的索引,采用Lucene索引具有如下優(yōu)勢(shì):- 1. neo4j的內(nèi)嵌索引采用b樹(shù),其僅能夠?qū)TARTS WITH、ENDS WITH、完全相等三種條件起作用。而lucene建立的全文索引能夠?qū)θ我馄蔚淖址M(jìn)行查詢。
- 2. lucene索引能夠?qū)Χ鄠€(gè)label建立.
- 3. lucene索引能夠?qū)σ坏蕉鄠€(gè)關(guān)系建立.
- 4. 能夠同時(shí)應(yīng)用于多個(gè)屬性。與內(nèi)嵌索引的Composite Index不同。Composite Index僅對(duì)滿足label且同時(shí)具有所有屬性的實(shí)體起作用,而全文索引則對(duì)至少滿足一個(gè)label、關(guān)系類型、屬性的節(jié)點(diǎn)或關(guān)系起作用.
1. call和yield的用法
首先看看這兩個(gè)詞的用方法。CALL語(yǔ)句用于調(diào)用數(shù)據(jù)庫(kù)中的過(guò)程(Procedure),YIELD子句用于顯示的選擇返回結(jié)果集中的哪些部分并綁定到一個(gè)變量以供后續(xù)查詢引用。簡(jiǎn)單說(shuō)就是用call來(lái)調(diào)用函數(shù),用yield來(lái)接收函數(shù)返回的結(jié)果。我們舉個(gè)例子
call db.labels() yield label
return count(label) as num
這里是調(diào)用數(shù)據(jù)庫(kù)中內(nèi)嵌的過(guò)程db.labels()計(jì)算數(shù)據(jù)庫(kù)中的總標(biāo)簽數(shù)。返回結(jié)果
2. 索引
在Neo4j中,有兩種不同的索引類型:B-樹(shù)和全文索引
可以使用Cypher創(chuàng)建和刪除B-樹(shù)索引。用戶通常不必知道索引就可以使用它,因?yàn)镃ypher的查詢計(jì)劃器會(huì)決定在哪種情況下使用哪個(gè)索引。B-樹(shù)索引擅長(zhǎng)于對(duì)所有類型的值進(jìn)行精確查找,以及范圍掃描,完整掃描和前綴搜索。比如(=,>,start with,contains)等
全文索引與B-樹(shù)索引不同,它們針對(duì)索引和搜索文本進(jìn)行了優(yōu)化。它們用于需要理解語(yǔ)言的查詢,并且僅索引字符串?dāng)?shù)據(jù)。還必須通過(guò)過(guò)程明確查詢它們。全文索引需要手動(dòng)去創(chuàng)建它,查詢的時(shí)候也是手動(dòng)去調(diào)用。
在理解了索引的兩種概念后,我們著手看看全文索引怎么創(chuàng)建。
3. 創(chuàng)建全文索引
在第一節(jié)中用到了db.labels()的過(guò)程,那有沒(méi)有內(nèi)置創(chuàng)建全文索引的過(guò)程呢。答案當(dāng)然是有了。會(huì)發(fā)現(xiàn)有db.index.fulltext.createNodeIndex(),那就用這個(gè)過(guò)程來(lái)開(kāi)始創(chuàng)建一個(gè)全文索引。在Dao層代碼如下,其中創(chuàng)建索引的名稱,標(biāo)簽和字段通過(guò)動(dòng)態(tài)傳參傳過(guò)去的,比如在公司,產(chǎn)品上創(chuàng)建公司名稱,產(chǎn)品名稱的全文索引名稱為allFullIndex
可以手動(dòng)從CQL查詢界面進(jìn)行創(chuàng)建
比如從GoodDes標(biāo)簽的name上創(chuàng)建全文索引, 并使用cjk分詞器
CALL db.index.fulltext.createNodeIndex("FT_GOODDES",["GoodDes"],["name"],{analyzer:"cjk", eventually_consistent:"true"})CALL db.index.fulltext.queryNodes("FT_GOODDES", "氣體導(dǎo)流管(舊)") YIELD node, score WHERE score > 0.6 MATCH (node)-[:GoodAndCode]->(goodCode:GoodCode) RETURN ID(node) AS nodeId, node.name AS goodDesName, score, ID(goodCode) AS goodCodeId, goodCode.code AS goodCodeCode;
@Repository
public interface FullIndexRepository extends Neo4jRepository<CompanyEntryNode, String> {/*** 創(chuàng)建索引** @param indexName 索引名稱* @param labels 標(biāo)簽名稱* @param properties 屬性*/@Query("call db.index.fulltext.createNodeIndex({indexName},{labels},{properties})")void createFullIndex(String indexName, String[] labels, String[] properties);/*** 刪除索引** @param indexName 索引名稱*/@Query("call db.index.fulltext.drop({indexName})")void deleteFullIndexByName(String indexName);
}
service層和controller層就不寫(xiě)了,直接調(diào)用我們創(chuàng)建的過(guò)程,就成功創(chuàng)建了一個(gè)名稱為allFullIndex的全文索引。
4. 查詢索引
同樣的有創(chuàng)建索引的過(guò)程,也有查詢?nèi)乃饕倪^(guò)程db.index.fulltext.queryNodes()
,那我們?cè)赿ao層做如下定義。這里結(jié)果中返回了node和score。score就是按照相似度給出的一個(gè)分值,分詞器會(huì)影響這個(gè)分值,node就是創(chuàng)建索引的節(jié)點(diǎn)信息。結(jié)果默認(rèn)是按照score數(shù)值從高到低返回。
@Repository
public interface BaseSearchRepository extends Neo4jRepository<CompanyEntryNode, String> {/*** 查詢?nèi)臋z索數(shù)據(jù)** @param searchWord* @return*/@Query("call db.index.fulltext.queryNodes('allFullIndex',{searchWord}) yield node,score " +"return node.name as name,score")List<BaseSearchDto> fullTextSearch( String searchWord);}
在controller層中我們調(diào)用會(huì)返回如下結(jié)果
這樣整個(gè)全文索引的創(chuàng)建和查詢就完成了。
5. 其他調(diào)用過(guò)程 [一]
db.index.fulltext.drop()
描述 | 刪除指定的索引。 |
---|---|
用法 | db.index.fulltext.drop(indexName :: STRING?) :: VOID |
db.index.fulltext.createNodeIndex()
描述 | 為給定的標(biāo)簽和屬性創(chuàng)建節(jié)點(diǎn)全文索引??蛇x的“ config”映射參數(shù)可用于為索引提供設(shè)置。支持的設(shè)置是“分析器”,用于指定在建立索引和查詢時(shí)要使用的分析器。使用以下db.index.fulltext.listAvailableAnalyzers 步驟查看可用的選項(xiàng)??梢詫ⅰ痚ventually_consistent’設(shè)置為’true’,以使該索引最終保持一致,從而將來(lái)自提交事務(wù)的更新應(yīng)用于后臺(tái)線程。 |
---|---|
語(yǔ)法 | db.index.fulltext.createNodeIndex(indexName :: STRING?, labels :: LIST? OF STRING?, properties :: LIST? OF STRING?, config = {} :: MAP?) :: VOID |
db.index.fulltext.createRelationshipIndex()
描述 | 查詢給定的全文索引。返回匹配關(guān)系及其Lucene查詢分?jǐn)?shù),按分?jǐn)?shù)排序。選項(xiàng)映射的有效鍵是:'skip’跳過(guò)前N個(gè)結(jié)果;'limit’限制返回的結(jié)果數(shù)。 |
---|---|
用法 | `db.index.fulltext.queryRelationships(indexName :: STRING?, queryString :: STRING?, options = {} :: MAP?) :: (relationship :: RELATIONSHIP?, score :: FLOAT?)``` |
db.index.fulltext.queryRelationships()
描述 | 為給定的關(guān)系類型和屬性創(chuàng)建一個(gè)關(guān)系全文本索引。可選的“ config”映射參數(shù)可用于為索引提供設(shè)置。支持的設(shè)置是“分析器”,用于指定在建立索引和查詢時(shí)要使用的分析器。使用以下db.index.fulltext.listAvailableAnalyzers 步驟查看可用的選項(xiàng)。可以將’eventually_consistent’設(shè)置為’true’,以使該索引最終保持一致,從而將來(lái)自提交事務(wù)的更新應(yīng)用于后臺(tái)線程。 |
---|---|
用法 | db.index.fulltext.createRelationshipIndex(indexName :: STRING?, relationshipTypes :: LIST? OF STRING?, properties :: LIST? OF STRING?, config = {} :: MAP?) :: VOID |
db.index.fulltext.queryNodes()
描述 | 查詢給定的全文索引。返回匹配的節(jié)點(diǎn)及其Lucene查詢分?jǐn)?shù),按分?jǐn)?shù)排序。選項(xiàng)映射的有效鍵是:'skip’跳過(guò)前N個(gè)結(jié)果;'limit’限制返回的結(jié)果數(shù)。 |
---|---|
用法 | db.index.fulltext.queryNodes(indexName :: STRING?, queryString :: STRING?, options = {} :: MAP?) :: (node :: NODE?, score :: FLOAT?) |
db.index.fulltext.listAvailableAnalyzers()
描述 | 列出可以配置全文本索引的可用分析器。 |
---|---|
用法 | db.index.fulltext.listAvailableAnalyzers() :: (analyzer :: STRING?, description :: STRING?, stopwords :: LIST? OF STRING?) |
6. 其他調(diào)用過(guò)程 [二]
https://blog.csdn.net/xiaqingyin/article/details/105567306
7. 舉例 - 創(chuàng)建和配置、查詢、刪除全文索引
使用全文索引進(jìn)行創(chuàng)建
例如,想要對(duì)于Label為Movie和Book的節(jié)點(diǎn)創(chuàng)建索引,索引的字段包括title和description。則采用如下cypher語(yǔ)句。
CALL db.index.fulltext.createNodeIndex("titlesAndDescriptions",["Movie", "Book"],["title", "description"])
想要使用以上索引搜索標(biāo)題或者描述中包含“matrix”的節(jié)點(diǎn),調(diào)用如下cypher語(yǔ)句。
CALL db.index.fulltext.queryNodes("titlesAndDescriptions", "matrix") YIELD node, score
RETURN node.title, node.description, score
創(chuàng)建關(guān)系索引,以及可選參數(shù)config的使用。
CALL db.index.fulltext.createRelationshipIndex("taggedByRelationshipIndex",["TAGGED_AS"],["taggedByUser"], { analyzer: "url_or_email", eventually_consistent: "true" })
使用全文索引進(jìn)行查詢
CALL db.index.fulltext.queryNodes("titlesAndDescriptions", "Full Metal Jacket") YIELD node, score
RETURN node.title, score
可以用Lucene的全文檢索語(yǔ)法,例如,如果需要完全匹配,則加雙引號(hào)
CALL db.index.fulltext.queryNodes("titlesAndDescriptions", "\"Full Metal Jacket\"") YIELD node, score
RETURN node.title, score
可以使用邏輯操作符,例如AND OR
CALL db.index.fulltext.queryNodes("titlesAndDescriptions", 'full AND metal') YIELD node, score
RETURN node.title, score
還可以對(duì)指定的屬性進(jìn)行查詢。
CALL db.index.fulltext.queryNodes("titlesAndDescriptions", 'description:"surreal adventure"') YIELD node, score
RETURN node.title, node.description, score
刪除全文索引
CALL db.index.fulltext.drop("taggedByRelationshipIndex")
8. 全文檢索之中文分詞器
其實(shí)用了這么久,我感覺(jué)用不用中文的全文索引影響不是很大
說(shuō)說(shuō)二種方式實(shí)現(xiàn)中文全文索引的創(chuàng)建。
1). 利用系統(tǒng)自帶的分詞器
我們?cè)趧?chuàng)建全文索引函數(shù)的時(shí)候是可以指定索引的分詞器的,他的分詞器可用下邊的方式查詢:
call db.index.fulltext.listAvailableAnalyzers
查到很多系統(tǒng)自帶的分詞器,其中有一個(gè)是“cjk”是針對(duì)中國(guó),日本,韓國(guó)做的分詞器,所以說(shuō)是支持中文分詞的。所以可以這樣建索引,像下邊指定analyzer的類型為“cjk”就指定的分詞器的類型。
CALL db.index.fulltext.createNodeIndex("companyFullIndex",["CompanyEntry"],["name"], { analyzer: "cjk"}
2). 通過(guò)第三方庫(kù)來(lái)創(chuàng)建全文索引
參考https://zhuanlan.zhihu.com/p/364927850
未驗(yàn)證
通過(guò)查找有第三方庫(kù)neo4j-graph-plugin-1.0.1.jar,這個(gè)不確定是不是官方的還是別人提供的,git下載地址:
https://github.com/crazyyanchao/ongdb-lab-apoc
下載neo4j-graph-plugin-1.0.1.jar文件,放到neo4j的plugins目錄下,該插件對(duì)應(yīng)的ik版本為:IKAnalyzer-5.0,支持LUCENE-5.5.0。修改配置文件,然后重啟neo4j服務(wù)。
dbms.security.procedures.unrestricted=apoc.*,zdr.*
安裝好后執(zhí)行,如果不報(bào)錯(cuò),表示安裝成功。初次會(huì)失敗!
RETURN zdr.apoc.hello("你好") as greeting
運(yùn)行函數(shù)zdr.index.iKAnalyzer會(huì)報(bào)莫名其妙的錯(cuò)誤,經(jīng)過(guò)測(cè)試需要繼續(xù)從https://github.com/crazyyanchao/neo4j-graph-plugin下載neo4j-graph-plugin-master.zip文件,解壓縮后取出其中的dic目錄拷貝到neo4j根目錄下,否則一直運(yùn)行失敗,因?yàn)樗枰曳衷~文件目錄,和java中引用IK分詞一樣。dic目錄下的分詞文件user_defined.dic可以添加自定義的分詞。如果想修改用戶自定義詞典的位置,可以修改配置文件:
vim dic/dic-cfg/IKAnalyzer.cfg.xml
以上配置好了之后創(chuàng)建中文索引,CompanyFullIndex是索引名稱,CompanyEntry是節(jié)點(diǎn)。
CALL zdr.index.addChineseFulltextIndex('CompanyFullIndex', ["name"], 'CompanyEntry') YIELD message RETURN message
這里的語(yǔ)法和系統(tǒng)庫(kù)里的稍微參數(shù)位置不一樣,其他邏輯都是一樣的。查詢的方法如下。
CALL zdr.index.chineseFulltextIndexSearch('CompanyFullIndex', 'name:測(cè)試~') YIELD node RETURN node