RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1300936
Accepted
Evendie
Evendie
Asked:2022-07-01 19:56:44 +0000 UTC2022-07-01 19:56:44 +0000 UTC 2022-07-01 19:56:44 +0000 UTC

Lucene如何将文本中单词的位置与IndexWriter给出的位置匹配?

  • 772

我将文本存储在 fileContent 变量中:

created: 2003-09-22T19:01:14Z
Author: be590_guest

GUERRILLA WAR, COUNTERINSURGENCY, AND STATE 

FORMATION IN OTTOMAN YEMEN 
 

如果用空格分隔符将其拆分成单词,并翻译成TextWord类的一个对象,然后尝试显示内容,可以看到:


TextWord[0]: created:
TextWord[1]: 2003-09-22T19:01:14Z
Author:
TextWord[2]: be590_guest



TextWord[3]: 
GUERRILLA
TextWord[4]: WAR,
TextWord[5]: COUNTERINSURGENCY,
TextWord[6]: AND
TextWord[7]: STATE
TextWord[8]: 

FORMATION
TextWord[9]: IN
TextWord[10]: OTTOMAN
TextWord[11]: YEMEN

在 fileContent 变量上创建索引后:

//Создание индекса по данным из файла
    public void createIndex(String content) throws IOException {
        
        IndexWriterConfig indexWriterConfig = new IndexWriterConfig(new StandardAnalyzer());
        try (IndexWriter writer = new IndexWriter(this.memoryIndex, indexWriterConfig)) {
            Document doc = new Document();
            FieldType type = new FieldType();
            type.setStoreTermVectors(true);
            type.setStoreTermVectorPositions(true);
            type.setStoreTermVectorOffsets(true);
            type.setStored(true);
            type.setIndexOptions(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS);
            Field fieldStore = new Field("tags", content, type); //В поле "tags" записываются данные из переменной content
            doc.add(fieldStore);
            writer.addDocument(doc);
        }
        catch(Exception e){
            e.printStackTrace();
        }
    }

为此,我使用新的 StandardAnalyzer()。

创建索引后,我想使用此创建的索引在文本文件内容中找到“状态”一词:

        String query_pattern = "state"; //Что хочу найти в тексте
        
        DirectoryReader reader = DirectoryReader.open(this.memoryIndex); //Взять индекс из памяти
        IndexSearcher searcher = new IndexSearcher(reader); //Создать поисковик по индексу

        //Поиск по одному слову
        Query query = new QueryParser("tags", analyzer).parse(query_pattern.toLowerCase()); //Запрос на поиск слова по полю tags
        TopDocs results = searcher.search(query, 1); //Результат поиска
        
        for (ScoreDoc scoreDoc : results.scoreDocs) { //Если слово было найдено, то...

            Fields termVs = reader.getTermVectors(scoreDoc.doc);
            Terms f = termVs.terms("tags");

            BytesRef ref = new BytesRef(query_pattern.toLowerCase()); //Шаблон в байтах для проверки

            TermsEnum te = f.iterator();
            PostingsEnum docsAndPosEnum = null;
            if (te.seekExact(ref)) { //Если нашли такое слово из шалона, то...

                //Узнать позицию и число повторений этого слова
                docsAndPosEnum = te.postings(docsAndPosEnum, PostingsEnum.ALL);
                int nextDoc = docsAndPosEnum.nextDoc();
                assert nextDoc != DocIdSetIterator.NO_MORE_DOCS;
                final int freg = docsAndPosEnum.freq();
                final int pos = docsAndPosEnum.nextPosition();
                final int o = docsAndPosEnum.startOffset();

                System.out.println("Word: " + ref.utf8ToString());
                System.out.println("[1] of [" + freg + "] Position: " + pos + ", startOffset: " + o + " length: " + ref.length + " Freg: " + freg);

                if (freg > 1) { //Число повторений слова в тексте
                    int i = 2;
                    for (int iter = 1; iter <= freg - 1; iter++) {
                        final int posNext = docsAndPosEnum.nextPosition();
                        System.out.println("[" + i + "] of [" + freg + "] Possition: " + posNext);
                        i++;
                    }
                }
            }
        }

单词被定位并显示其位置:

Word: state
Position: 12

我转到我的 TextWord 并且位置 12 没有这样的词,或者没有这样的位置,然后我显示索引中的所有术语及其位置,按顺序排列它们:

            Fields termVs = reader.getTermVectors(scoreDoc.doc);
            Terms f = termVs.terms("tags");
            TermsEnum te = f.iterator();
            PostingsEnum docsAndPosEnum = null;
            BytesRef bytesRef;

            while ((bytesRef = te.next()) != null) { //Пройтись по всем словам из индекса

                docsAndPosEnum = te.postings(docsAndPosEnum, PostingsEnum.ALL);
                int nextDoc = docsAndPosEnum.nextDoc();
                assert nextDoc != DocIdSetIterator.NO_MORE_DOCS;
                final int fr = docsAndPosEnum.freq();
                final int pos = docsAndPosEnum.nextPosition();
                final int o = docsAndPosEnum.startOffset();

                System.out.println("Word: " + bytesRef.utf8ToString());
                System.out.println("Position: " + pos + ", startOffset: " + o + " length: " + bytesRef.length + " Freg: " + fr);
                sortIndexWord.put(bytesRef.utf8ToString(), pos);

                if (fr > 1) {
                    for (int iter = 1; iter <= fr - 1; iter++) {
                        int posNext = docsAndPosEnum.nextPosition();
                        //System.out.println("Possition: " + posNext);
                        sortIndexWord.put(bytesRef.utf8ToString()+String.valueOf(iter), posNext);
                    }

                }

            }

我得到了这个数据:

IndexWord: [0]: created
IndexWord: [1]: 2003
IndexWord: [2]: 09
IndexWord: [3]: 22t19
IndexWord: [4]: 01
IndexWord: [5]: 14z
IndexWord: [6]: author
IndexWord: [7]: be590_guest
IndexWord: [8]: guerrilla
IndexWord: [9]: war
IndexWord: [10]: counterinsurgency
IndexWord: [12]: state
IndexWord: [13]: formation
IndexWord: [15]: ottoman
IndexWord: [16]: yemen

可以看出他从位置 11 中去掉了 And 这个词,State 变成了 12,但是如果我只是尝试显示标记,使用与新的 StandardAnalyzer() 索引相同:

public List<String> analyze(String text, Analyzer analyzer) throws IOException {
        List<String> result = new ArrayList<String>();
        TokenStream tokenStream = analyzer.tokenStream("tags", text);
        CharTermAttribute attr = tokenStream.addAttribute(CharTermAttribute.class);
        tokenStream.reset();
        while (tokenStream.incrementToken()) {
            result.add(attr.toString());
        }
        return result;
    }

    List<String> list = analyze(myContent, new StandardAnalyzer());
    for(int ik = 0 ; ik <= list.size()-1; ik++){
        System.out.println("ListWord["+ik+"]: "+list.get(ik));
    }

可以看出:

ListWord[0]: created
ListWord[1]: 2003
ListWord[2]: 09
ListWord[3]: 22t19
ListWord[4]: 01
ListWord[5]: 14z
ListWord[6]: author
ListWord[7]: be590_guest
ListWord[8]: guerrilla
ListWord[9]: war
ListWord[10]: counterinsurgency
ListWord[11]: state
ListWord[12]: formation
ListWord[13]: ottoman
ListWord[14]: yemen

And这个词又被删除了,但同时我还有其他索引,我猜不出他删除了哪些词,哪些没有。


问题是,如何将文本中单词的位置与 IndexWriter 给出的位置相匹配?请告诉我如何,提前谢谢。

java
  • 1 1 个回答
  • 10 Views

1 个回答

  • Voted
  1. Best Answer
    Roman-Stop RU aggression in UA
    2022-07-02T02:52:54Z2022-07-02T02:52:54Z

    我转到我的 TextWord 并在第 12 位

    lucene 对你的TextWord. 而position这与他无关。这是文本中某个位置的一些抽象标识符(在简单的情况下,我们可以假设这是一个标记号,但这完全取决于分析器,它的设置会改变,这个数字将失去意义)。

    And这个词又被删除了,但同时我还有其他索引,我猜不出他删除了哪些词,哪些没有

    你不需要它。需要分析过程,以便 lucene 知道如何将文本分解为单词。您提交文本作为输入,并且您正在寻找单词,有时不仅仅是一个单词,而是几个单词。分析器设置什么是分隔符的规则,是否需要用连字符单独和/或一起索引单词等。它与匹配在文本中的位置无关,因为 分析器转换输入文本 - 它可以转换一些单词(例如,更改大小写或替换缩写),可以丢弃一些单词,可以将某些东西粘合在一起,甚至可以从现有单词的片段中插入新单词。您还需要在原始文本中的位置,即 在被分析仪处理之前。

    主要问题是PostingsEnum 您不需要positions,但是offsets。startOffset指向存储字段 valueendOffset中的开始索引和结束索引,即 在您在索引期间传递并存储在索引中的那个中。值本身可以这样获得:

    int docid = scoreDoc.doc;
    Document doc = searcher.doc(docid);
    String text = doc.get("tags");   // сохраненное значение поля
    String match = text.substring(docsAndPosEnum.startOffset(), docsAndPosEnum.endOffset());
    
    

    查看此示例https://howtodoinjava.com/lucene/lucene-search-highlight-example/和 -a 的源代码 Highligher,了解它如何使用offsets它来获取高亮值。

    • 1

相关问题

  • wpcap 找不到指定的模块

  • 如何以编程方式从桌面应用程序打开 HTML 页面?

  • Android Studio 中的 R.java 文件在哪里?

  • HashMap 初始化

  • 如何使用 lambda 表达式通过增加与原点的距离来对点进行排序?

  • 最大化窗口时如何调整元素大小?

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    表格填充不起作用

    • 2 个回答
  • Marko Smith

    提示 50/50,有两个,其中一个是正确的

    • 1 个回答
  • Marko Smith

    在 PyQt5 中停止进程

    • 1 个回答
  • Marko Smith

    我的脚本不工作

    • 1 个回答
  • Marko Smith

    在文本文件中写入和读取列表

    • 2 个回答
  • Marko Smith

    如何像屏幕截图中那样并排排列这些块?

    • 1 个回答
  • Marko Smith

    确定文本文件中每一行的字符数

    • 2 个回答
  • Marko Smith

    将接口对象传递给 JAVA 构造函数

    • 1 个回答
  • Marko Smith

    正确更新数据库中的数据

    • 1 个回答
  • Marko Smith

    Python解析不是css

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5