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

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. thinkphp+layui多图上传(1)thinkphp5+layui实现多图上传保存到数据库,可以实现图片自由排序,自由删除。

    公共css代码 <style> .layui-upload-img { width: 90px; height: 90px; margin: 0; } .pic-more { width: ...

  2. AntiPlug

    反插件工程 #pragma once #ifndef __ENHANFUNC_H__ #define __ENHANFUNC_H__ #include <iostream> #includ ...

  3. Tomcat运行错误示例三

    Tomcat运行错误示例三 最近碰到tomcat启动的问题,如图: 以前也碰见过这种情况,这次写的时候忘记加return,所以跳出了错误,加上之后的效果,如图: 参考网址 参考网址

  4. 输入流当中的read方法和readfully方法的区别与原理

    原文链接:https://blog.csdn.net/yangjingyuan/article/details/6151234?locationNum=3 DataInputStream类中的read ...

  5. CSS3 Media Queries模板:max-width和min-width

    CSS3 Media Queries模板 CSS3 Media Queries一般都是使用“max-width”和“min-width”两个属性来检查各种设备的分辨大小与样式表所设条件是否满足,如果满 ...

  6. Mac上Chrome浏览器跨域解决方案

    现在比较新的浏览器在本地调试时AJAX请求,基本都会有跨域问题.相应的解决方案也挺多的,工具也不少.像charles等抓包工具等.不过最简单的就是移除浏览器的同源限制. 我们要做的第一步,就是创建一个 ...

  7. Interview - 面试题汇总目录

    参考 java 入门面试题 https://blog.csdn.net/meism5/article/details/89021536 一.Java 基础 1.JDK 和 JRE 有什么区别? 2.= ...

  8. Spring容器对Bean组件的管理

    Bean对象创建 默认是随着容器创建 可以使用 lazy-init=true:在调用 getBean 延迟创建 也可以用 <beans default-lazy-init="true& ...

  9. Android 防止切换横屏闪退

    <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="ht ...

  10. CSS案例1(导航栏)

    文本的装饰 text-decoration 通常我们用于给链接修改装饰效果 使用技巧:在一行内的盒子内,我们设定行高等于盒子的高度,就可以使文字垂直居中. <head> <meta ...