com.browseengine.bobo.geosearch.index.impl.GeoQueryTest.java Source code

Java tutorial

Introduction

Here is the source code for com.browseengine.bobo.geosearch.index.impl.GeoQueryTest.java

Source

/**
 * This software is licensed to you under the Apache License, Version 2.0 (the
 * "Apache License").
 *
 * LinkedIn's contributions are made under the Apache License. If you contribute
 * to the Software, the contributions will be deemed to have been made under the
 * Apache License, unless you expressly indicate otherwise. Please do not make any
 * contributions that would be inconsistent with the Apache License.
 *
 * You may obtain a copy of the Apache License at http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, this software
 * distributed under the Apache License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the Apache
 * License for the specific language governing permissions and limitations for the
 * software governed under the Apache License.
 *
 *  2012 LinkedIn Corp. All Rights Reserved.  
 */

package com.browseengine.bobo.geosearch.index.impl;

import static org.junit.Assert.assertTrue;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.TreeSet;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.RAMDirectory;
import org.apache.lucene.util.Version;
import org.junit.Test;

import com.browseengine.bobo.geosearch.bo.CartesianGeoRecord;
import com.browseengine.bobo.geosearch.bo.GeoSearchConfig;
import com.browseengine.bobo.geosearch.bo.LatitudeLongitudeDocId;
import com.browseengine.bobo.geosearch.impl.CartesianGeoRecordComparator;
import com.browseengine.bobo.geosearch.impl.CartesianGeoRecordSerializer;
import com.browseengine.bobo.geosearch.impl.GeoConverter;
import com.browseengine.bobo.geosearch.impl.GeoRecordBTree;
import com.browseengine.bobo.geosearch.index.bo.GeoCoordinate;
import com.browseengine.bobo.geosearch.query.GeoQuery;
import com.browseengine.bobo.geosearch.query.GeoScorer;
import com.browseengine.bobo.geosearch.query.GeoWeight;
import com.browseengine.bobo.geosearch.score.impl.Conversions;
import com.browseengine.bobo.geosearch.score.impl.HaversineComputeDistance;

public class GeoQueryTest {
    private GeoIndexReader geoIndexReader;
    List<GeoSegmentReader<CartesianGeoRecord>> geoSubReaders;

    private static class MyGeoSegmentReader extends GeoSegmentReader<CartesianGeoRecord> {
        private final GeoRecordBTree tree;

        public MyGeoSegmentReader(GeoRecordBTree tree, int maxDoc) {
            super(tree.getArrayLength(), maxDoc, new CartesianGeoRecordSerializer(),
                    new CartesianGeoRecordComparator());
            this.tree = tree;
        }

        /**
         * Delegates to the GeoRecordBTree from the constructor.
         * 
         * {@inheritDoc}
         */
        @Override
        protected CartesianGeoRecord getValueAtIndex(int index) {
            return tree.getValueAtIndex(index);
        }
    }

    @Test
    public void test_Test() throws IOException {
        GeoCoordinate gcord = new GeoCoordinate(Math.random() * 140.0 - 70.0, Math.random() * 360.0 - 180.0);
        float rangeInKm = (float) (Math.random() * 10.0);
        float rangeInMiles = Conversions.km2mi(rangeInKm);
        ArrayList<LatitudeLongitudeDocId> indexedDocument = getSegmentOfLongitudeLatitudeDocIds(
                100 + (int) (Math.random() * 1000), gcord);

        printAllDocIdsInRange(rangeInMiles, indexedDocument, gcord);

        TreeSet<CartesianGeoRecord> treeSet = arrayListToTreeSet(indexedDocument);
        GeoRecordBTree geoRecordBTree = new GeoRecordBTree(treeSet);
        MyGeoSegmentReader geoSegmentReader = new MyGeoSegmentReader(geoRecordBTree, indexedDocument.size());
        geoSubReaders = new ArrayList<GeoSegmentReader<CartesianGeoRecord>>();
        geoSubReaders.add(geoSegmentReader);

        GeoQuery geoQuery = new GeoQuery(gcord.getLatitude(), gcord.getLongitude(), rangeInKm);
        GeoWeight geoWeight = (GeoWeight) geoQuery.createWeight(null);
        Directory directory = buildEmptyDirectory();
        geoIndexReader = new GeoIndexReader(directory, new GeoSearchConfig());
        geoIndexReader.setGeoSegmentReaders(geoSubReaders);
        boolean scoreInOrder = true, topScorer = true;
        GeoScorer geoScorer = (GeoScorer) geoWeight.scorer(geoIndexReader, scoreInOrder, topScorer);
        test_Scorer(rangeInMiles, geoScorer, gcord, indexedDocument);
    }

    private void printAllDocIdsInRange(float rangeInMiles, ArrayList<LatitudeLongitudeDocId> indexedDocument,
            GeoCoordinate gcord) {

        System.err.println("Enter the is doc in range check.");
        Iterator<LatitudeLongitudeDocId> it = indexedDocument.iterator();
        HaversineComputeDistance hcd = new HaversineComputeDistance();
        LatitudeLongitudeDocId lldid = null;
        while (it.hasNext()) {
            lldid = it.next();
            if (hcd.getDistanceInMiles(gcord.getLongitude(), gcord.getLatitude(), lldid.longitude,
                    lldid.latitude) < rangeInMiles) {
                System.err.println("Document id within range is: " + lldid.docid);
            }
        }

    }

    private void test_Scorer(float rangeInKm, GeoScorer geoScorer, GeoCoordinate gcord,
            ArrayList<LatitudeLongitudeDocId> indexedDocument) throws IOException {

        ArrayList<Integer> recordRangeHitsDocIds = new ArrayList<Integer>();
        HaversineComputeDistance hcd = new HaversineComputeDistance();
        int doc = geoScorer.nextDoc();
        while (doc != geoScorer.NO_MORE_DOCS) {
            recordRangeHitsDocIds.add(new Integer(doc));
            //            assertTrue("Hit out of range! ", 
            //                    hcd.getDistanceInMiles(gcord.getLongitude(), 
            //                                           gcord.getLatitude(),
            //                                           indexedDocument.get(doc).longitude,
            //                                           indexedDocument.get(doc).latitude)
            //                    <= rangeInMiles);
            doc = geoScorer.nextDoc();
        }

        Iterator<LatitudeLongitudeDocId> it = indexedDocument.iterator();
        int docid;
        while (it.hasNext()) {
            docid = it.next().docid;
            if (!recordRangeHitsDocIds.contains(new Integer(docid))) {
                assertTrue("Document less than " + rangeInKm + "KM from centroid but not considered a hit ",
                        Conversions.mi2km(hcd.getDistanceInMiles(gcord.getLongitude(), gcord.getLatitude(),
                                indexedDocument.get(docid).longitude,
                                indexedDocument.get(docid).latitude)) > rangeInKm);
            }
        }
    }

    private Directory buildEmptyDirectory() throws IOException {
        RAMDirectory directory = new RAMDirectory();
        Version version = Version.LUCENE_CURRENT;
        Analyzer analyzer = new StandardAnalyzer(version);
        IndexWriterConfig indexWriterConfig = new IndexWriterConfig(version, analyzer);
        IndexWriter writer = new IndexWriter(directory, indexWriterConfig);
        writer.close();
        return directory;
    }

    public TreeSet<CartesianGeoRecord> arrayListToTreeSet(ArrayList<LatitudeLongitudeDocId> indexedDocument) {
        TreeSet<CartesianGeoRecord> treeSet = new TreeSet<CartesianGeoRecord>(new CartesianGeoRecordComparator());
        GeoConverter gc = new GeoConverter();
        for (int i = 0; i < indexedDocument.size(); i++) {
            treeSet.add(gc.toCartesianGeoRecord(indexedDocument.get(i), (byte) 0));
        }
        return treeSet;
    }

    public ArrayList<LatitudeLongitudeDocId> getSegmentOfLongitudeLatitudeDocIds(int len, GeoCoordinate gcord) {
        int docid = 0;
        ArrayList<LatitudeLongitudeDocId> segmentOfLongitudeLatitudeDocIds = new ArrayList<LatitudeLongitudeDocId>();
        for (int i = 0; i < len; i++) {
            segmentOfLongitudeLatitudeDocIds.add(getNewRandomLongitudeLatitudeDocId(docid++, gcord));
        }
        return segmentOfLongitudeLatitudeDocIds;
    }

    public LatitudeLongitudeDocId getNewRandomLongitudeLatitudeDocId(int docid, GeoCoordinate gcord) {
        return new LatitudeLongitudeDocId(gcord.getLatitude() + Math.random() * 0.4 - 0.2, //Math.random() * 360.0 - 180.0,
                gcord.getLongitude() + Math.random() * 0.4 - 0.2, //Math.random() * 180.0 - 90.0,
                docid);
    }
}