Lucene 8.4.1 - LatLonShape.createIndexableFields против RecursivePrefixTreeStrategy.createIndexableFields - PullRequest
0 голосов
/ 17 февраля 2020

Я работаю с Lucene версии 8.4.1 и получил несколько вопросов о пространственной индексации. Речь идет о производительности, а затем о пространственном поиске. Мои тестовые данные около 10000 полигонов. Это небольшой набор данных.

Прежде всего, мои настройки:

            // JtsSpaticalContext is needed to index polygons
            this.ctx = JtsSpatialContext.GEO;
            SpatialPrefixTree tree = new GeohashPrefixTree(this.ctx, MAX_LEVEL);
            this.strategy = new RecursivePrefixTreeStrategy(tree, GEOMETRY_FIELDNAME);
            this.shapeReader = this.ctx.getFormats().getWktReader();
            // Creating the path for lucene index files
            Path path = Paths.get(INDEX_FOLDER);
            this.dir = SimpleFSDirectory.open(path);

            // preparing IndexWriter
            IndexWriterConfig config = new IndexWriterConfig(new StandardAnalyzer());           
            config.setOpenMode(OpenMode.CREATE);
            config.setRAMBufferSizeMB(256.0);
            config.setUseCompoundFile(false);           
            config.setMaxBufferedDocs(IndexWriterConfig.DISABLE_AUTO_FLUSH);

            LogMergePolicy policy = new LogDocMergePolicy();
            policy.setMergeFactor(15);
            config.setMergePolicy(policy);

            this.indexWriter = new IndexWriter(dir, config);

Как вы можете видеть, я использую JtsSpatialContext для индексации моих пространственных данных. Конфиг для меня все еще волшебный c, это консульство дало мне лучшие результаты. MAX_LEVEL для GeohashPrefixTree установлено в 11. Также: this.shapeReader = this.ctx.getFormats (). GetWktReader используется для избавления от Устаревший предупреждение, которое отображается, когда я использую ctx.readFromWkt . Я наблюдал за SpatialExample. java от официального репо Lucene Github Github Repo SpatialExample

Теперь, как я уже сказал, я хочу проиндексировать ~ 10000 полигонов, которые находятся в Мой случай использования небольшой набор данных. У меня есть два подхода для индексации этих данных, отличающиеся на CaseA и CaseB

Вот мой логик c, как я добавляю эти полигоны в свой индекс:

        // Start Case A
        List<String> testDataCaseA = new ArrayList<>();     
        for (int i = 0; i < 10000; i++) {
            testDataCaseA.add("POLYGON((9.0842201 48.80324419974113,9.084344 48.803237199741126,9.0843574 48.80333909974109,9.0842334 48.8033461997411,9.0842201 48.80324419974113))");
        }

        long startCaseA = System.nanoTime();

        testDataCaseA.parallelStream().forEach(current -> {
            try {
                this.indexWriter.addDocument(createDocumentCaseA(current));
            } catch (InvalidShapeException | IOException | java.text.ParseException e) {
                logger.error(e.toString());
            }
        });

        double elapsedTimeCaseA = (System.nanoTime() - startCaseA) / 1000000;
        logger.trace("Elapsed Time: " + elapsedTimeCaseA + "ms");
        // End Case A

        // Deleting the index
        this.indexWriter.deleteAll();

        // Start Case B
        List<String> testDataCaseB = new ArrayList<>(); 
        for (int i = 0; i < 10000; i++) {
            testDataCaseB.add("{\"type\":\"Polygon\",\"coordinates\":[[[9.0842201,48.80324419974113],[9.084344,48.803237199741126],[9.0843574,48.80333909974109],[9.0842334,48.8033461997411],[9.0842201,48.80324419974113]]]}");
        }

        long startCaseB = System.nanoTime();

        testDataCaseB.parallelStream().forEach(current -> {
            try {
                this.indexWriter.addDocument(createDocumentCaseB(current));
            } catch (java.text.ParseException | IOException e) {
                logger.error(e.toString());
            }
        });

        double elapsedTimeCaseB = (System.nanoTime() - startCaseB) / 1000000;
        logger.trace("Elapsed Time: " + elapsedTimeCaseB + "ms");
        // End Case B

А вот методы createDocumentCaseA и createDocumentCaseB

    private Document createDocumentCaseA(String geom) throws java.text.ParseException, InvalidShapeException, IOException {
        Document doc = new Document();

        for (Field f : strategy.createIndexableFields(this.shapeReader.read(geom))) {
            doc.add(f);
        }

        return doc;
    }

    private Document createDocumentCaseB(String geom) throws java.text.ParseException {
        Document doc = new Document();

        for (Polygon poly : Polygon.fromGeoJSON(geom)) {
            for (Field f : LatLonShape.createIndexableFields(GEOMETRY_FIELDNAME, poly)) {
                doc.add(f);
            }
        }

        return doc;
    }

Разница между этими двумя вариантами поразительна:

Истекшее время случая A: 41522,0 мс

Истекшее время случая B: 168,0 мс

Ну, я подумал: "Хм, хорошо, тогда я просто выбираю случай B и все в порядке". Но моя проблема на «понятном уровне»: каков «правильный» способ сделать это? И еще: если я использую пространственный поиск, в CaseA я получил метод strategy.makeQuery (SpatialArgs) , в CaseB мне нужно использовать LatLonShape.createXYQuery (someStuff)

Какой способ выбрать? Я что-то упустил в документах от Lucene?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...