public void testPointValuesMemoryIndexVsNormalIndex() throws Exception { int size = atLeast(12); List<Integer> randomValues = new ArrayList<>(); Document doc = new Document(); for (Integer randomInteger : random().ints(size).toArray()) { doc.add(new IntPoint("int", randomInteger)); randomValues.add(randomInteger); doc.add(new LongPoint("long", randomInteger)); doc.add(new FloatPoint("float", randomInteger)); doc.add(new DoublePoint("double", randomInteger)); } MockAnalyzer mockAnalyzer = new MockAnalyzer(random()); MemoryIndex memoryIndex = MemoryIndex.fromDocument(doc, mockAnalyzer); IndexSearcher memoryIndexSearcher = memoryIndex.createSearcher(); Directory dir = newDirectory(); IndexWriter writer = new IndexWriter(dir, newIndexWriterConfig(random(), mockAnalyzer)); writer.addDocument(doc); writer.close(); IndexReader controlIndexReader = DirectoryReader.open(dir); IndexSearcher controlIndexSearcher = new IndexSearcher(controlIndexReader); Supplier<Integer> valueSupplier = () -> randomValues.get(random().nextInt(randomValues.size())); Query[] queries = new Query[] { IntPoint.newExactQuery("int", valueSupplier.get()), LongPoint.newExactQuery("long", valueSupplier.get()), FloatPoint.newExactQuery("float", valueSupplier.get()), DoublePoint.newExactQuery("double", valueSupplier.get()), IntPoint.newSetQuery("int", valueSupplier.get(), valueSupplier.get()), LongPoint.newSetQuery("long", valueSupplier.get(), valueSupplier.get()), FloatPoint.newSetQuery("float", valueSupplier.get(), valueSupplier.get()), DoublePoint.newSetQuery("double", valueSupplier.get(), valueSupplier.get()), IntPoint.newRangeQuery("int", valueSupplier.get(), valueSupplier.get()), LongPoint.newRangeQuery("long", valueSupplier.get(), valueSupplier.get()), FloatPoint.newRangeQuery("float", valueSupplier.get(), valueSupplier.get()), DoublePoint.newRangeQuery("double", valueSupplier.get(), valueSupplier.get()) }; for (Query query : queries) { assertEquals(controlIndexSearcher.count(query), controlIndexSearcher.count(query)); } memoryIndexSearcher.getIndexReader().close(); controlIndexReader.close(); dir.close(); }
/** * Returns a numeric range query based on FieldType {@link LegacyNumericRangeQuery} is used for * indexes created using {@code FieldType.LegacyNumericType} {@link DoublePoint#newRangeQuery} is * used for indexes created using {@link DoublePoint} fields */ private Query rangeQuery(String fieldName, Double min, Double max) { if (hasPointVals) { if (min == null) { min = Double.NEGATIVE_INFINITY; } if (max == null) { max = Double.POSITIVE_INFINITY; } return DoublePoint.newRangeQuery(fieldName, min, max); } else if (legacyNumericFieldType != null) { // todo remove legacy numeric support in 7.0 return LegacyNumericRangeQuery.newDoubleRange( fieldName, legacyNumericFieldType.numericPrecisionStep(), min, max, true, true); // inclusive } // TODO try doc-value range query? throw new UnsupportedOperationException("An index is required for this operation."); }
/** * Given a latitude and longitude (in degrees) and the maximum great circle (surface of the earth) * distance, returns a simple Filter bounding box to "fast match" candidates. */ public static Query getBoundingBoxQuery( double originLat, double originLng, double maxDistanceKM) { // Basic bounding box geo math from // http://JanMatuschek.de/LatitudeLongitudeBoundingCoordinates, // licensed under creative commons 3.0: // http://creativecommons.org/licenses/by/3.0 // TODO: maybe switch to recursive prefix tree instead // (in lucene/spatial)? It should be more efficient // since it's a 2D trie... // Degrees -> Radians: double originLatRadians = SloppyMath.toRadians(originLat); double originLngRadians = SloppyMath.toRadians(originLng); double angle = maxDistanceKM / EARTH_RADIUS_KM; double minLat = originLatRadians - angle; double maxLat = originLatRadians + angle; double minLng; double maxLng; if (minLat > SloppyMath.toRadians(-90) && maxLat < SloppyMath.toRadians(90)) { double delta = Math.asin(Math.sin(angle) / Math.cos(originLatRadians)); minLng = originLngRadians - delta; if (minLng < SloppyMath.toRadians(-180)) { minLng += 2 * Math.PI; } maxLng = originLngRadians + delta; if (maxLng > SloppyMath.toRadians(180)) { maxLng -= 2 * Math.PI; } } else { // The query includes a pole! minLat = Math.max(minLat, SloppyMath.toRadians(-90)); maxLat = Math.min(maxLat, SloppyMath.toRadians(90)); minLng = SloppyMath.toRadians(-180); maxLng = SloppyMath.toRadians(180); } BooleanQuery.Builder f = new BooleanQuery.Builder(); // Add latitude range filter: f.add( DoublePoint.newRangeQuery( "latitude", SloppyMath.toDegrees(minLat), SloppyMath.toDegrees(maxLat)), BooleanClause.Occur.FILTER); // Add longitude range filter: if (minLng > maxLng) { // The bounding box crosses the international date // line: BooleanQuery.Builder lonF = new BooleanQuery.Builder(); lonF.add( DoublePoint.newRangeQuery( "longitude", SloppyMath.toDegrees(minLng), Double.POSITIVE_INFINITY), BooleanClause.Occur.SHOULD); lonF.add( DoublePoint.newRangeQuery( "longitude", Double.NEGATIVE_INFINITY, SloppyMath.toDegrees(maxLng)), BooleanClause.Occur.SHOULD); f.add(lonF.build(), BooleanClause.Occur.MUST); } else { f.add( DoublePoint.newRangeQuery( "longitude", SloppyMath.toDegrees(minLng), SloppyMath.toDegrees(maxLng)), BooleanClause.Occur.FILTER); } return f.build(); }
private void _run() throws IOException { for (int i = 0; i < iters; i++) { String color; String sortField; switch (random.nextInt(4)) { case 0: // TermQuery on yellow cabs color = "y"; if (sparse) { sortField = "yellow_pickup_longitude"; } else { sortField = "pickup_longitude"; } break; case 1: // TermQuery on green cabs color = "g"; if (sparse) { sortField = "green_pickup_longitude"; } else { sortField = "pickup_longitude"; } break; case 2: // BooleanQuery on both cabs (all docs) color = "both"; sortField = null; break; case 3: // Point range query color = "neither"; sortField = null; break; default: throw new AssertionError(); } Query query; if (color.equals("both")) { BooleanQuery.Builder builder = new BooleanQuery.Builder(); builder.add(new TermQuery(new Term("cab_color", "y")), BooleanClause.Occur.SHOULD); builder.add(new TermQuery(new Term("cab_color", "g")), BooleanClause.Occur.SHOULD); query = builder.build(); } else if (color.equals("neither")) { if (sparse) { BooleanQuery.Builder builder = new BooleanQuery.Builder(); builder.add( DoublePoint.newRangeQuery("green_pickup_latitude", 40.75, 40.9), BooleanClause.Occur.SHOULD); builder.add( DoublePoint.newRangeQuery("yellow_pickup_latitude", 40.75, 40.9), BooleanClause.Occur.SHOULD); query = builder.build(); } else { query = DoublePoint.newRangeQuery("pickup_latitude", 40.75, 40.9); } } else { query = new TermQuery(new Term("cab_color", color)); } Sort sort; if (sortField != null && random.nextBoolean()) { sort = new Sort(new SortField(sortField, SortField.Type.DOUBLE)); } else { sort = null; } long t0 = System.nanoTime(); TopDocs hits; if (sort == null) { hits = searcher.search(query, 10); } else { hits = searcher.search(query, 10, sort); } long t1 = System.nanoTime(); results.add( "T" + threadID + " " + query + " sort=" + sort + ": " + hits.totalHits + " hits in " + ((t1 - t0) / 1000000.) + " msec"); for (ScoreDoc hit : hits.scoreDocs) { Document doc = searcher.doc(hit.doc); results.add(" " + hit.doc + " " + hit.score + ": " + doc.getFields().size() + " fields"); } /* synchronized(printLock) { System.out.println("T" + threadID + " " + query + " sort=" + sort + ": " + hits.totalHits + " hits in " + ((t1-t0)/1000000.) + " msec"); for(ScoreDoc hit : hits.scoreDocs) { Document doc = searcher.doc(hit.doc); System.out.println(" " + hit.doc + " " + hit.score + ": " + doc.getFields().size() + " fields"); } } */ } }