全文检索中近义词、关联词的解决方案

同义词腾讯api

一直想找到一个好的同义词解决方案,在百度和google查找,大家对于这个问题都只是寥寥数语,不愿讲清,我在javaeye搜此类信息也求不到,后来发了个提问贴也只有浏览数而无回复,不知道这是什么原因,无奈之下我只有自己研究。

因为没有其它的解决方案可以借鉴,以下纯为我个人的见解。

我认为所谓近义词、关联词检索不外乎以下三种形式:

1.类似google suggest,用户输入关键字后自动提示功能。

2.假如“奥运会”的关联词是“北京”,用户输入“奥运会”搜索时,将“奥运会”的搜索结果以及“北京”的搜索结果都搜出来。

3.用户输入“奥运会”搜索,只显示“奥运会”的结果,它的关联词在结果集的底端用“相关搜索”的形式提示给用户。

这三种方式中看似2和3是类似的,其实还是有些很大区别的,我个人认为在实际的应用中,第3种方式是最多见的。

先说说第1种方式

google suggest的在网上可以搜到完整的解决方案,跟我此前想的一样。

建一个用来存储关键字的表

例如:

  1. create table  KEYS(
  2. ITEM_ID varcha2(50) not null,
  3. SEARCH_KEY varchar2(100),
  4. );

SEARCH_KEY里存储一些检索的关键字,如“奥运”,“奥运会”,“北京奥运会”等.

当用户在文本框敲入时,使用AJAX将当前文本框的内容发到Action,进行下面类似的操作

  1. String key = request.getParameter("inputValue");
  2. String sql = "select * from KEYS as k where k.SEARCH_KEY like ‘%key%‘";

这个办法也就是把当前文本框中的字放到数据库中做模糊查询,比如用户输入“奥”这个字,会从搜出所有包含“奥”字的词,然后将这些词包装好,发回至页面,页面上用JS画出下拉框,将这些包含“奥”字的词填入就可以了。

google做的是右边匹配,即是用的 like ‘key%‘ ,输入“奥”字,会出现所有以“奥”字开头的词的提示。

大家应该注意到google suggest的提示词的最后面都写有“约XXXXX条记录”,我现在唯一能想到的解决方案是,当我们在Action中拿到匹配的词之后,将匹配的词搜索一次即可得出具体记录的条数,其实这样也不耗多少资源。

第2种方式

将关键词和关键词所联的词的结果都搜出来

我个人认为这个功能在实际的应用中只需用到其5%就可以了,因为在用户体验方面考虑,我们必须保障搜索结果的质量。关键词的近义词可以在结果页的底端提示给用户,也就是我上边说到的第3种方式。

我所说的只需用到5%的意思是只需为少数的、必须转义的词实现这样的功能

比如搜索“China”,那么“中国”这个词的结果肯定得出现在结果集里,还有比如搜索“08”,那么“2008”的结果也得出现在结果集里,这些都是一些特定情况,其它的词没必要做成这样,只需做提示即可。

现在中文检索一般都是基于词库的检索,实现第2种方式这个功能必须将之前的词库以及分词算法进行修改。

一般的方法是在词库中把同义词写成一行,如将“中国 China”写在同一行,然后修改Token算法(这个大家可以去研究一下,我现在使用的Analyzer包是公司商业上的伙伴提供的测试包,这个测试包已经可以满足很大一部分需求了,我还不知道能不能共享)

其实原理是在索引时将原词和原词的近义词一起索引

具体给大家个例子

有这样一句话  ---- “中国是世界上人口最多的国家”

如果没有为其做同义词,大家可能会索引成这样

[中国][世界][人口][最多][国家]

如果做了同义词,会索引成

[中国][China][世界][人口][最多][国家]

即是说在索引时就已经将“中国”这个词存成[中国][China]了,搜索时无论搜“中国”或是“China”都可以搜到这句话。

其实这个功能相当大一部分是依赖第三方的jar包,说来说去也没多大意思,并且大多数情况下我们需要的并不同这种功能,而是更人性化的查询提示的功能,也就是第3种方式。

第3种方式

这种方式是我在原有的系统上改进完成的

原有的系统是 compass + paoding + lucene

由于我不太熟compass的搜索,所以我还是采用的lucene搜索。相信大家对这种搭配的全文检索已经非常熟悉了,paoding的词库是可以自己配置的。

那么怎样在原有的基础实现关键词提示功能呢???

我的做法是这样的,我按照paoding词库的特点新建了一个mydictionary.dic文件放在classpath下,里面的内容大致如下。

第1行:奥运会  北京  2008  第29届奥运会

第2行:中国 China 中华人民共和国 中国电信 中国人民银行

........

然后在服务器启动时,将mydictionary.dic这个文件中的文字一行行读入,分别做索引

  1. InputStream fi = this.getClass().getClassLoader().getResourceAsStream("mydictionary.dic");
  2. File indexDir = new File("d:\\tong");
  3. Analyzer luceneAnalyzer = new StandardAnalyzer();
  4. IndexWriter indexWriter = new IndexWriter(indexDir, luceneAnalyzer,true);
  5. BufferedReader reader = new BufferedReader(new InputStreamReader(fi, "UTF-8"));
  6. String line = new String();
  7. while ((line = reader.readLine()) != null)
  8. {
  9. Document document = new Document();
  10. Field FieldName = new Field("line", line,Field.Store.YES, Field.Index.TOKENIZED);
  11. document.add(FieldName);
  12. indexWriter.addDocument(document);
  13. }
  14. indexWriter.optimize();
  15. indexWriter.close();
  16. reader.close();

在搜索时,对用户输入的关键字正常搜索出结果后,对关键字进行第二次搜索,搜的是同义词的索引,得到的结果按空格分开,即可得到所有同义词,然后将同义词发送至页面即可。

  1. public List getTongYi(String searchword) throws Exception
  2. {
  3. List list = new ArrayList();
  4. Hits hits = null;
  5. String queryString = searchword;
  6. Query query = null;
  7. String result = "";
  8. IndexSearcher searcher = new IndexSearcher("d:\\tong");
  9. Analyzer analyzer = new StandardAnalyzer();
  10. QueryParser qp = new QueryParser("line", analyzer);
  11. query = qp.parse(queryString);
  12. if (searcher != null)
  13. {
  14. hits = searcher.search(query);
  15. for(int i=0;i<hits.length();i++)
  16. {
  17. Document doc = hits.doc(i);
  18. System.out.println((i+1)+"."+doc.get("line"));
  19. result = doc.get("line");
  20. }
  21. }
  22. if(result!=null && !result.equals(""))
  23. {
  24. String [] manyresult = result.split(" ");
  25. for(int i=0;i<manyresult.length;i++)
  26. {
  27. if(manyresult[i]!=null && !manyresult[i].trim().equals(""))
  28. {
  29. list.add(manyresult[i]);
  30. }
  31. }
  32. }
  33. return list;
  34. }

我觉得做同义词索引和搜索的时候最好用StandardAnalyzer,切成单字是最符合的。

写了这么多,如果各位有更好的想法不妨发出来一起研究一下。

时间: 2024-08-26 08:22:56

全文检索中近义词、关联词的解决方案的相关文章

近义词调研评估与代码实现(不断完善中…)

  1.确定要解决的问题及意义 在基于代码片段的分类过程中,由于程序员对数据变量名的选取可能具有一定的规范性,在某一特定业务处理逻辑代码中,可能多个变量名之间具有关联性或相似性(如“trade”(商品交易)类中,可能存在“business”,“transaction”,“deal”等同义词),在某些情况下,它们以不同的词语表达了相同的含义.因此,为了能够对代码片段做出更加科学的类别判断,更好地识别这些同义词,我们有必要寻找一种能够解决避免由于同义词的存在而导致误分类的方法.说白了,就是要去判断词

算法--近义词反义词

今天参加ACM校选,真的是伤心的到绝望,今年就没编过C++,语法都忘得差不多了,弄个helloWordl! 搞了20来分钟,简直日了狗.数组的传递忘干净了(自己太菜,比赛不知为啥死活调用函数时候无法传数组)报错,拿java编代码便习惯了,换到C艹各种艹啊.所以考到一半就放弃了.看着身边的大神一道道做完,自己哎,只做了2道,校选都过不去!!!!!眼睁睁看着题会做,不会用C++在纸上写java代码,心里这个苦.所以要拿c++编代码,用C++,用C++. 当然今天我还是拿java把这次比赛见到的一个蛮

基于WordNet的英文同义词、近义词相似度评估及代码实现

作者:max_xbw 1.确定要解决的问题及意义 在基于代码片段的分类过程中,由于程序员对数据变量名的选取可能具有一定的规范性,在某一特定业务处理逻辑代码中,可能多个变量名之间具有关联性或相似性(如“trade”(商品交易)类中,可能存在“business”,“transaction”,“deal”等同义词),在某些情况下,它们以不同的词语表达了相同的含义.因此,为了能够对代码片段做出更加科学的类别判断,更好地识别这些同义词,我们有必要寻找一种能够解决避免由于同义词的存在而导致误分类的方法.说白

句子逆序,近义词维护,数字颠倒,蛇形矩阵

一.句子逆序描述:  将一个英文语句以单词为单位逆序排放.例如“I am a boy”,逆序排放后为“boy a am I” 所有单词之间用一个空格隔开,语句中除了英文字母外,不再包含其他字符 接口说明 /**  * 反转句子  *   * @param sentence 原句子  * @return 反转后的句子  */ public String reverse(String sentence); 1 public class StringReverse { 2 public static

OJ初级-句子逆序,近义词维护,数字颠倒,蛇形矩阵

备注:所有基础的练习题都不能借助相应功能的工具函数 一.句子逆序描述:  将一个英文语句以单词为单位逆序排放.例如“I am a boy”,逆序排放后为“boy a am I” 所有单词之间用一个空格隔开,语句中除了英文字母外,不再包含其他字符 接口说明 /**  * 反转句子  *   * @param sentence 原句子  * @return 反转后的句子  */ public String reverse(String sentence); 二.近义词维护 给定接口,设置两个单词相互

java实现近义词维护

题目要求:一.近义词维护 给定接口,设置两个单词相互近义.近义词具有相互传递性,如果A和B为近义词,B和C是近义词,那么A.B.C都为近义词.要求提供接口,查询给定的两个但是是否是近义词关系.并且能提供接口清除所有的近义词关系. 接口说明 /**  * 设置2个单词为近义词  * @param word1 单词一  * @param word2 单词二  * @return 0为成功,-1为失败或其他异常  */ public int setSynonyms(String word1, Stri

比较结构的关联词(二)

一.比较结构的关联词(二) 11. nothing but = nothing else than = nothing less than 不是别的...正是...;完全是:无异于 Genius is nothing else but labor and diligence. 译文:天才不过是劳动加勤奋而已 12.much less = still less 更不,更无 I could not agree to ,much less participate in such proceedings

【ACL2019】利用关联词与关系词的对应性,通过标签嵌入识别隐性话语关系

Employing the Correspondence of Relations and Connectives to Identify Implicit Discourse Relations via Label Embeddings 利用关联词与关系词的对应性,通过标签嵌入识别隐性话语关系 Introduction Discourse parsing reveals the discourse units (i.e., text spans, sentences, clauses) of

NLP—WordNet——词与词之间的最小距离

WordNet,是由Princeton 大学的心理学家,语言学家和计算机工程师联合设计的一种基于认知语言学的英语词典.它不是光把单词以字母顺序排列,而且按照单词的意义组成一个"单词的网络".我们这次的任务就是求得词与词之间的最短路径,是对"图"这个数据结构再次灵活运用. 以下为SentiWordNet_3.0.0_20130122.txt文件截图: 应考虑如何存储"单词的网络",此程序是以词作为基本单元,词与词之间的联系是通过语义. 我们简单地构