資料庫檢索效率時,一般首要優化途徑是從索引入手,然後根據需求再考慮更復雜的負載均衡、讀寫分離和分散式水平/垂直分庫/表等手段;索引通過資訊冗餘來提高檢索效率,其以空間換時間並會降低資料寫入的效率,因此對索引欄位的選擇非常重要。

Neo4j可對指定Label的Node Create Index,當新增/更新符合條件的Node屬性時,Index會自動更新。Neo4j Index預設採用Lucene實現(可定製,如Spatial Index自定義實現的RTree索引),但預設新建的索引只支援精確匹配(get),模糊查詢(query)的話需要以全文索引,控制Lucene後臺的分詞行為。

Neo4j全文索引預設的分詞器是針對西方語種的,如預設的exact查詢採用的是lucene KeywordAnalyzer(關鍵詞分詞器),fulltext查詢採用的是 white-space tokenizer(空格分詞器),大小寫什麼的對中文沒啥意義;所以針對中文分詞需要掛一箇中文分詞器,如IK Analyzer,Ansj,至於類似樑廠長家的基於深度學習的分詞系統pullword,那就更厲害啦。

本文以常用的IK Analyzer分詞器為例,介紹如何在Neo4j中對欄位新建全文索引實現模糊查詢。

IKAnalyzer分詞器

IKAnalyzer是一個開源的,基於java語言開發的輕量級的中文分詞工具包。

IKAnalyzer3.0特性

  • 採用了特有的“正向迭代最細粒度切分演算法“,支援細粒度和最大詞長兩種切分模式;具有83萬字/秒(1600KB/S)的高速處理能力。

  • 採用了多子處理器分析模式,支援:英文字母、數字、中文詞彙等分詞處理,相容韓文、日文字元優化的詞典儲存,更小的記憶體佔用。支援使用者詞典擴充套件定義

  • 針對Lucene全文檢索優化的查詢分析器IKQueryParser(作者吐血推薦);引入簡單搜尋表示式,採用歧義分析演算法優化查詢關鍵字的搜尋排列組合,能極大的提高Lucene檢索的命中率。
    IK Analyser目前還沒有maven庫,還得自己手動下載install到本地庫,下次空了自己在github做一個maven私有庫,上傳這些maven central庫裡面沒有的工具包。

IKAnalyzer自定義使用者詞典

詞典檔案

自定義詞典字尾名為.dic的詞典檔案,必須使用無BOM的UTF-8編碼儲存的檔案。

詞典配置

詞典和IKAnalyzer.cfg.xml配置檔案的路徑問題,IKAnalyzer.cfg.xml必須在src根目錄下。詞典可以任意放,但是在IKAnalyzer.cfg.xml裡要配置對。如下這種配置,ext.dic和stopword.dic應當在同一目錄下。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>IK Analyzer 擴充套件配置</comment>
<!--使用者可以在這裡配置自己的擴充套件字典 -->
<entry key="ext_dict">/ext.dic;</entry>
<!--使用者可以在這裡配置自己的擴充套件停止詞字典-->
<entry key="ext_stopwords">/stopword.dic</entry>
</properties>

Neo4j全文索引構建

指定IKAnalyzer作為luncene分詞的analyzer,並對所有Node的指定屬性新建全文索引

  @Override
public void createAddressNodeFullTextIndex () {
try (Transaction tx = graphDBService.beginTx()) {
IndexManager index = graphDBService.index();
Index<Node> addressNodeFullTextIndex =
index.forNodes( "addressNodeFullTextIndex", MapUtil.stringMap(IndexManager.PROVIDER, "lucene", "analyzer", IKAnalyzer.class.getName()));
ResourceIterator<Node> nodes = graphDBService.findNodes(DynamicLabel.label( "AddressNode"));
while (nodes.hasNext()) {
Node node = nodes.next();
//對text欄位新建全文索引
Object text = node.getProperty( "text", null);
addressNodeFullTextIndex.add(node, "text", text);
}
tx.success();
}
}

Neo4j全文索引測試

對關鍵詞(如’有限公司’),多關鍵詞模糊查詢(如’蘇州 教育 公司’)預設都能檢索,且檢索結果按關聯度已排好序。

package uadb.tr.neodao.test;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Transaction;
import org.neo4j.graphdb.index.Index;
import org.neo4j.graphdb.index.IndexHits;
import org.neo4j.graphdb.index.IndexManager;
import org.neo4j.helpers.collection.MapUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.wltea.analyzer.lucene.IKAnalyzer;
import com.lt.uadb.tr.entity.adtree.AddressNode;
import com.lt.util.serialize.JsonUtil;
/**
* AddressNodeNeoDaoTest
*
* @author geosmart
*/
@RunWith(SpringJUnit4ClassRunner. class)
@ContextConfiguration(locations = { "classpath:app.neo4j.cfg.xml" })
public class AddressNodeNeoDaoTest {
@Autowired
GraphDatabaseService graphDBService;
@Test
public void test_selectAddressNodeByFullTextIndex() {
try (Transaction tx = graphDBService.beginTx()) {
IndexManager index = graphDBService.index();
Index<Node> addressNodeFullTextIndex = index.forNodes("addressNodeFullTextIndex" ,
MapUtil. stringMap(IndexManager.PROVIDER, "lucene", "analyzer" , IKAnalyzer.class.getName()));
IndexHits<Node> foundNodes = addressNodeFullTextIndex.query("text" , "蘇州 教育 公司" );
for (Node node : foundNodes) {
AddressNode entity = JsonUtil.ConvertMap2POJO(node.getAllProperties(), AddressNode. class, false, true);
System. out.println(entity.getAll地址實全稱());
}
tx.success();
}
}
}

CyperQL中使用自定義全文索引查詢

正則查詢

profile
match (a:AddressNode{ruleabbr:'TOW',text:'唯亭鎮'})<-[r:BELONGTO]-(b:AddressNode{ruleabbr:'STR'})
where b.text=~ '金陵.*'
return a,b

全文索引查詢

profile
START b=node:addressNodeFullTextIndex("text:金陵*")
match (a:AddressNode{ruleabbr:'TOW',text:'唯亭鎮'})<-[r:BELONGTO]-(b:AddressNode)
where b.ruleabbr='STR'
return a,b

LegacyIndex中建立聯合exact和fulltext索引

對label為AddressNode的節點,根據節點屬性ruleabbr的分類addressnode_fulltext_index(省->市->區縣->鄉鎮街道->街路巷/物業小區)/addressnode_exact_index(門牌號->樓幢號->單元號->層號->戶室號),對屬性text分別建不同型別的索引

profile
START a=node:addressnode_fulltext_index("text:商業街"),b=node:addressnode_exact_index("text:二期19")
match (a:AddressNode{ruleabbr:'STR'})-[r:BELONGTO]-(b:AddressNode{ruleabbr:'TAB'})
return a,b limit 10

原文地址:https://codertw.com/%e8%b3%87%e6%96%99%e5%ba%ab/10006/

Neo4j中實現自定義中文全文索引的更多相关文章

  1. Q郵箱轉移自定義目錄中的郵件

    1.之前在Q郵箱上建立了許多規則和收件箱,現在想統一用Mac上的郵局管理 2.Mac上會同步對應郵箱的自定義目錄,此時這些目錄便十分多餘礙眼 3.Q郵箱單頁顯示郵件數量上限是100,這意味著手動轉移十 ...

  2. 可以支持jQuery1.10.1 的 fancybox 1.3.4, 並現在type為Ajax時,也可以定義窗口的大小。

    官網上的 fancybox 1.3.4 太老了,不支持jQuery1.10.1,改動了一下源碼,現在可以支持了. type為Ajax時,也可以定義窗口的大小. $("#ajaxlink&qu ...

  3. 在Android中afinal框架下實現sqlite數據庫版本升級的辦法

    public abstract void onUpgrade(SQLiteDatabase db,int oldVersion,int new Version) 這個方法在實現時需要重寫.   pub ...

  4. Neo4j中实现自定义中文全文索引

    数据库检索效率时,一般首要优化途径是从索引入手,然后根据需求再考虑更复杂的负载均衡.读写分离和分布式水平/垂直分库/表等手段:索引通过信息冗余来提高检索效率,其以空间换时间并会降低数据写入的效率:因此 ...

  5. [實現DDD] 第10章 聚合(1)設計原則

    聚合只是將一些實體(Entity)與值對象(Value Object)聚集起來的對象樹嗎?? 有些途徑可能使我們設計出不正確的聚合模型, 如:可能為了對象組合上的方便而將聚合設計的很大;也可能設計的聚 ...

  6. dataTable.NET的column index的不同定義

    dataTable.NET是一個jQuery的plug in 第三方的library, 用來實現web page中table的interaction controls, 另外最近有在用的還有Teler ...

  7. Linux Ubuntu 虛擬機系統自定義桌面分辨率且重啓後保持不變

    我用 VMware Workstation 12 Pro 安裝的 Ubuntu MATE Desktop Environment 1.12.1,發現安裝後沒有需要的分辨率,於是安裝 VMware To ...

  8. 使用Mutex實現單一程式執行個體的注意事項(转)

    相信大家都知道在.NET程式中若要實現單一程式執行個體,一般來說有幾種方法,像是去判斷是否已經有開啟的Process是相同的程式.用Mutex與Semaphore之類的技術來判斷是否程式正在開啟.但是 ...

  9. #HTML:無序、有序與定義清單

    #HTML:無序.有序與定義清單 Maplewing 于 星期六, 12/10/2013 - 09:48 提交 清單在網頁中是很常使用到的東西,故多少還是要了解一下.在HTML中有三種不太一樣的清單, ...

随机推荐

  1. UVA - 10347 - Medians(由三中线求三角形面积)

    AC代码: #include<cstdio> #include<cmath> #include<algorithm> #include<iostream> ...

  2. 剑指offer——40字符串的排列

    题目描述 输入一个字符串,按字典序打印出该字符串中字符的所有排列.例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba. 输入描述: 输 ...

  3. JMeter轻松实现大数据量AI图像识别接口测试

    ****************************************************************************** 本文主要介绍利用Jmeter进行AI图像识 ...

  4. print的简单使用

    import time num=20 for i in range(num): print("#", end="") 结果如下: 加个强制刷新 num=20 f ...

  5. Summary 报告

    1.需要在添加一个名为summary report的监听器,跑完之后查看 Label:取样器/监听器名称 Samples :事务数量 Average:平均一个完成一个事务消耗的时间(平均响应时间) M ...

  6. 磁盘设备在 Linux 下的表示方法

    在 Linux 系统中磁盘设备文件的命名规则为: 主设备号 + 次设备号 + 磁盘分区号 对于目前常见的磁盘,一般表示为: sd[a-z]x 主设备号代表设备的类型,相同的主设备号表示同类型的设备. ...

  7. cdn 的配置及原理

    CDN概况 CDN的全称是Content Delivery Network,即内容分发网络. CND加速主要是加速静态资源,如网站上面上传的图片.媒体,以及引入的一些Js.css等文件. CND加速需 ...

  8. asp.net MVC项目,localhost响应时间过长

    1.早上高高兴兴的吃完早餐,敲了几句代码,准备调试,竟然发现VS调试项目打开的很慢,最后报错如下图 2.那就很可能是IIS问题嘛,IIS重启了一下,还是不行,在地址栏输入localhost,如下图(本 ...

  9. redis安装到本地服务的方法

    要安装Redis,首先要获取安装包. Windows的Redis安装包需要到以下GitHub链接找到. 链接:https://github.com/MSOpenTech/redis 打开网站后,找到R ...

  10. leetcood学习笔记-59-螺旋矩阵二

    题目描述: 参考后的提交: class Solution: def generateMatrix(self, n: int): #l = [[0] * n] * n 此创建方法错误 l = [[] f ...