Как распечатать все термины из документа Lucene?

Я пытаюсь распечатать все термины из документов между двумя docID. Но некоторые термины, которые я проиндексировал, не печатаются.

Извините, потому что некоторые вещи написаны в Испании, потому что это проект для моего испанского университета.

У меня есть этот код:

package simpledemo;

import java.nio.file.Paths;
import java.util.List;
import java.util.ArrayList;

import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.index.Terms;
import org.apache.lucene.index.TermsEnum;
import org.apache.lucene.index.Fields;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.similarities.Similarity;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.BytesRef;
//import org.apache.lucene.search.similarities.DefaultSimilarity; // FIXME No se pq no detecta esto si aparece en el API de Lucene

public class TopTermsInDocs {


    public static void main(String[] args) {
        // TODO Poner bien el paquete al que pertenece cd ordenemos el codigo
        String usage = "simpledemo.TopTermsInDocs"
        + "[-index INDEX_PATH] [-docID INT1-INT2] [-top N] [-outfile PATH]\n"
        + "The result will be displayed on screen and in a file to be indicated in"
        + "the -outfile path argument, will show for each document its"
        + "docId and the top n terms with its tf, df and tf x idflog10";

        String indexPath = null; // TODO mirar si poner uno por defecto o hacer que falle
        String[] range = null;
        Integer docIdStart = null;
        Integer docIdEnd = null;
        Integer topN = null;
        String outPath = null;
        System.out.println(usage);

        for (int i = 0; i < args.length; i++) {
            switch(args[i]) {
                case "-index": 
                    indexPath = args[++i];
                    break;
                case "-docID":
                    range = args[++i].split("-");
                    docIdStart = Integer.parseInt(range[0]);
                    docIdEnd = Integer.parseInt(range[1]);
                    break;
                case "-top":
                    topN = Integer.parseInt(args[++i]);
                    break;
                case "-outfile":
                    outPath = args[++i];
            } 
        }
        IndexReader reader = null; //Ls inicializo aqui a null pq sino no los voy a poder usar fuera del try
        // FIXME descomentar cd lo reconozca       DefaultSimilarity similarity = new DefaultSimilarity();
        try {
            reader = DirectoryReader.open(FSDirectory.open(Paths.get(indexPath)));

            int numDocs = reader.numDocs(); // Numero de documentos total

            for(int id = docIdStart; id<docIdEnd; id++) {
                System.out.println("Voy a printear el docID: " + id);
                Fields fields = reader.getTermVectors(id); //Obtengo todos los terminos del documento

                for (String fieldName : fields) {
                    Terms terms = fields.terms(fieldName);
                    TermsEnum termsEnum = terms.iterator();
                    BytesRef term = null;

                    while((term = termsEnum.next()) != null) {
                        String termText = term.utf8ToString();
                        long termFreq = termsEnum.totalTermFreq(); //Frecuencia total del termino
                        int docFreq = termsEnum.docFreq(); //Frecuencia de documento
                        int tf = (int) Math.round(termFreq / docFreq); //Frecuencia del termino en el documento
                        // FIXME descomentar cd lo reconozca    double idf = similarity.idf(docFreq, numDocs);
                        int idf = (int) Math.log(numDocs/(docFreq+1)) + 1;
                        System.out.println("Campo: " + fieldName + " - Término: " + termText + " - tf: " + tf + " - idf: " + idf);
                        //TODO primero probar si funciona y si funciona puedo hacer una funcion que devuelva una estructura con todo
                    }

                }

                System.out.println("\n\n");
            }

        } catch (Exception e) {
            // TODO: handle exception
        }






    }
}

Я знаю, что параметры -top и -outfile на данный момент не реализованы. Но для проблемы это не имеет значения.

Когда я выполняю его для одного документа, он показывает:

Campo: LastModifiedTimeLucene - Término: 20230408150702014 - tf: 1 - idf: 2
Campo: contents - Término: david - tf: 1 - idf: 2
Campo: contents - Término: hola2 - tf: 1 - idf: 2
Campo: contents - Término: txt - tf: 1 - idf: 2
Campo: creationTime - Término: 2023-04-08 17:07:02 - tf: 1 - idf: 2
Campo: creationTimeLucene - Término: 20230408150702014 - tf: 1 - idf: 2
Campo: lastAccessTime - Término: 2023-04-09 01:10:26 - tf: 1 - idf: 2
Campo: lastAccessTimeLucene - Término: 20230408231026954 - tf: 1 - idf: 2
Campo: lastModifiedTime - Término: 2023-04-08 17:07:02 - tf: 1 - idf: 2

О создании документов у меня есть эта функция:

    void indexDoc(IndexWriter writer, Path file, long lastModified) throws IOException {
        System.out.println(file.getFileName().toString());
        // TODO Añadir la funcionalidad de onlyLines
        if (config.validateFile(file.getFileName().toString()))
        {
            try (InputStream stream = Files.newInputStream(file)) {
                // make a new, empty document
                Document doc = new Document();
                
                // Add the path of the file as a field named "path". Use a
                // field that is indexed (i.e. searchable), but don't tokenize
                // the field into separate words and don't index term frequency
                // or positional information:
                Field pathField = new StringField("path", file.toString(), Field.Store.YES);
                doc.add(pathField);
                
                String contents = obtainContents(stream);
                
                FieldType tmp_field_type = new FieldType();
                
                tmp_field_type.setTokenized(true);
                tmp_field_type.setIndexOptions(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS);
                tmp_field_type.setStoreTermVectors(contentsTermVectors);
                tmp_field_type.setStoreTermVectorPositions(contentsTermVectors);
                tmp_field_type.setStored(contentsStored);
                tmp_field_type.freeze();
                
                // Add the contents of the file to a field named "contents". Specify a Reader,
                // so that the text of the file is tokenized and indexed, but not stored.
                // Note that FileReader expects the file to be in UTF-8 encoding.
                // If that's not the case searching for special characters will fail.
                
                Field contentsField = new Field("contents", contents, tmp_field_type);
                doc.add(contentsField);

                // TODO Extender documentacion
                Field hostnameField = new StringField("hostname", InetAddress.getLocalHost().getHostName(), Field.Store.YES);
                doc.add(hostnameField);
    
                // TODO Extender documentacion
                Field threadField = new StringField("thread", Thread.currentThread().getName(), Field.Store.YES);
                doc.add(threadField);
                
                // TODO Extender documentacion
                
                BasicFileAttributes at = Files.readAttributes(file, BasicFileAttributes.class);
                String type;
                if (at.isDirectory()) type = "isDirectory";
                else if (at.isRegularFile()) type = "isRegularFile";
                else if (at.isSymbolicLink()) type = "iSSymbolicLink";
                else if (at.isOther()) type = "isOther";
                else type = "error";

                doc.add(new StringField("type", type, Field.Store.YES));
                
                // TODO Extender documentacion
                
                doc.add(new LongPoint("sizeKB", at.size())); // ! CUIDAO
                doc.add(new StoredField("sizeKB", at.size()));

                // Add the last modified date of the file a field named "modified".
                // Use a LongPoint that is indexed (i.e. efficiently filterable with
                // PointRangeQuery). This indexes to milli-second resolution, which
                // is often too fine. You could instead create a number based on
                // year/month/day/hour/minutes/seconds, down the resolution you require.
                // For example the long value 2011021714 would mean
                // February 17, 2011, 2-3 PM.
                doc.add(new LongPoint("modified", lastModified));
                doc.add(new StoredField("modified", lastModified));
    
                
                String dateFormat = "yyyy-MM-dd HH:mm:ss";
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat(dateFormat);

                FileTime creationTime = at.creationTime();
                String creationTimeFormateado = simpleDateFormat.format(new Date(creationTime.toMillis()));
                doc.add(new Field("creationTime", creationTimeFormateado, TYPE_STORED));

                FileTime lastAccessTime = at.lastAccessTime();
                String lastAccessTimeFormateado = simpleDateFormat.format(new Date(lastAccessTime.toMillis()));
                doc.add(new Field("lastAccessTime", lastAccessTimeFormateado, TYPE_STORED));

                FileTime lastModifiedTime = at.lastModifiedTime();
                String lastTimeModifiedTimeFormateado = simpleDateFormat.format(new Date(lastModifiedTime.toMillis()));
                doc.add(new Field("lastModifiedTime", lastTimeModifiedTimeFormateado, TYPE_STORED));

                Date creationTimelucene = new Date(creationTime.toMillis());
                String s1 = DateTools.dateToString(creationTimelucene, DateTools.Resolution.MILLISECOND);
                doc.add(new Field("creationTimeLucene", s1, TYPE_STORED));

                Date lastAccessTimelucene = new Date(lastAccessTime.toMillis());
                String s2 = DateTools.dateToString(lastAccessTimelucene, DateTools.Resolution.MILLISECOND);
                doc.add(new Field("lastAccessTimeLucene", s2, TYPE_STORED));

                Date lastModifiedTimelucene = new Date(lastModifiedTime.toMillis());
                String s3 = DateTools.dateToString(lastModifiedTimelucene, DateTools.Resolution.MILLISECOND);
                doc.add(new Field("LastModifiedTimeLucene", s3, TYPE_STORED));
                
                if (demoEmbeddings != null) {
                    try (InputStream in = Files.newInputStream(file)) {
                        float[] vector = demoEmbeddings.computeEmbedding(
                                new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8)));
                        doc.add(
                                new KnnVectorField("contents-vector", vector, VectorSimilarityFunction.DOT_PRODUCT));
                    }
                }
    
                if (writer.getConfig().getOpenMode() == OpenMode.CREATE) {
                    // New index, so we just add the document (no old document can be there):
                    System.out.println("adding " + file);
                    writer.addDocument(doc);
                } else {
                    // Existing index (an old copy of this document may have been indexed) so
                    // we use updateDocument instead to replace the old one matching the exact
                    // path, if present:
                    System.out.println("updating " + file);
                    writer.updateDocument(new Term("path", file.toString()), doc);
                }
            }
        }
        else
            System.out.println("Este archivo va a ser ignorado");
    }```

But I have indexed more fields for the document, like file type. Why are they not shown?

Какую версию Lucene вы используете? Как вы создали используемые вами документы (чтобы мы могли видеть, какие поля вы определили и как вы их определили).

andrewJames 09.04.2023 03:32

Я ожидаю, что вы будете использовать document.getFields(), если вам нужны поля для определенных документов — и имейте в виду, что поля, установленные в Field.Store.NO, не хранятся ни в каком конкретном документе, в индексе. Это разница между «полями для документа» (о чем, я думаю, вы просите) и «документами для поля».

andrewJames 09.04.2023 03:34

Я использую Lucene 9.4.2.

David 09.04.2023 11:48

Я отредактировал свой вопрос и добавил код, который я использую для индексации каждого документа.

David 09.04.2023 11:53
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
4
76
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы хотите распечатать определенные данные поля:

"из документов между двумя docID"

Отсутствующий пример, который вы конкретно упомянули, был «типом файла», например:

doc.add(new StringField("type", "isDirectory", Field.Store.YES));

Ожидается, что ваш код сможет получить доступ к этому полю, используя:

Fields fields = reader.getTermVectors(id);

Но поле type не является вектором термов. Это StringField, а именно:

Поле, которое индексируется, но не токенизируется: все значение String индексируется как один токен.

Вместо этого вы можете получить это поле, используя следующее:

reader.document(id).getFields()

Например (здесь я решил использовать forEach, но вы также можете использовать свой цикл):

for (int id = 0; id < 1; id++) {
    reader.document(id).getFields()
        .forEach(field -> System.out.println(field.name() 
        + " - " + field.stringValue()));
}

Для моего примера type приведенный выше код печатает:

type - isDirectory

Спасибо за правки к вашему вопросу. Использовать эти правки сложно, так как они не дают mre — есть отсылки к другим методам, тогда как некоторые жестко запрограммированные данные, вероятно, были бы полезнее — например, как мой пример:

doc.add(new StringField("type", "isDirectory", Field.Store.YES));

Это автономно и не зависит от каких-либо файлов или других методов, не указанных в вашем вопросе.

Если в вашем выводе есть дополнительные отсутствующие поля, вы можете посмотреть, какие это типы полей, и, возможно, предоставить пример жестко закодированных данных.

Возможно, для них даже стоит задать новый, более целенаправленный вопрос.

Другие вопросы по теме