pylucene 3.5.0-3
[pylucene.git] / lucene-java-3.5.0 / lucene / contrib / spatial / src / java / org / apache / lucene / spatial / tier / DistanceQueryBuilder.java
1 /**
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 package org.apache.lucene.spatial.tier;
19
20 import org.apache.lucene.search.ConstantScoreQuery;
21 import org.apache.lucene.search.ChainedFilter;
22 import org.apache.lucene.search.Filter;
23 import org.apache.lucene.search.Query;
24 import org.apache.lucene.search.QueryWrapperFilter;
25 import org.apache.lucene.spatial.geohash.GeoHashDistanceFilter;
26
27 /**
28  * <p><font color="red"><b>NOTE:</b> This API is still in
29  * flux and might change in incompatible ways in the next
30  * release.</font>
31  */
32 public class DistanceQueryBuilder {
33
34   private static final long serialVersionUID = 1L;
35   
36   private final double lat;
37   private final double lng;
38   private final double miles;
39   private final Filter filter;
40   final DistanceFilter distanceFilter;
41
42   /**
43    * Create a distance query using
44    * a boundary box wrapper around a more precise
45    * DistanceFilter.
46    * 
47    * @param lat The latitude to search around
48    * @param lng the Longitude to search around
49    * @param miles The radius to search within
50    * @param latField The name of the field containing the latitude
51    * @param lngField The name of the field containing the longitude
52    * @param tierFieldPrefix The prefix of the tier
53    * @param needPrecise if true, then distance is calculated in addition to tier info
54    * @param minTierIndexed The minimum tier level indexed
55    * @param maxTierIndexed The maximum tier level indexed
56    */
57   public DistanceQueryBuilder (double lat, double lng, double miles, 
58       String latField, String lngField, String tierFieldPrefix, boolean needPrecise, int minTierIndexed, int maxTierIndexed) {
59
60     this.lat = lat;
61     this.lng = lng;
62     this.miles = miles;
63     
64     CartesianPolyFilterBuilder cpf = new CartesianPolyFilterBuilder(tierFieldPrefix, minTierIndexed, maxTierIndexed);
65     Filter cartesianFilter = cpf.getBoundingArea(lat, lng, miles);
66
67     /* create precise distance filter */
68     if (needPrecise) {
69       filter = distanceFilter = new LatLongDistanceFilter(cartesianFilter, lat, lng, miles, latField, lngField);
70     } else {
71       filter = cartesianFilter;
72       distanceFilter = null;
73     }
74   }
75
76   /**
77    * Create a distance query using
78    * a boundary box wrapper around a more precise
79    * DistanceFilter.
80    * 
81    * @param lat
82    * @param lng
83    * @param miles
84    */
85   public DistanceQueryBuilder (double lat, double lng, double miles, 
86       String geoHashFieldPrefix, String tierFieldPrefix, boolean needPrecise,  int minTierIndexed, int maxTierIndexed){
87
88     this.lat = lat;
89     this.lng = lng;
90     this.miles = miles;
91     
92     CartesianPolyFilterBuilder cpf = new CartesianPolyFilterBuilder(tierFieldPrefix, minTierIndexed, maxTierIndexed);
93     Filter cartesianFilter = cpf.getBoundingArea(lat, lng, miles);
94
95     /* create precise distance filter */
96     if (needPrecise) {
97       filter = distanceFilter = new GeoHashDistanceFilter(cartesianFilter, lat, lng, miles, geoHashFieldPrefix);
98     } else {
99       filter = cartesianFilter;
100       distanceFilter = null;
101     }
102   }
103
104   
105   /**
106   * Create a distance query using
107   * a boundary box wrapper around a more precise
108   * DistanceFilter.
109   */
110   public Filter getFilter() {
111     if (distanceFilter != null) {
112       distanceFilter.reset();
113     }
114     return filter;
115   }
116   
117   public Filter getFilter(Query query) {
118     // Chain the Query (as filter) with our distance filter
119     if (distanceFilter != null) {
120       distanceFilter.reset();
121     }
122     QueryWrapperFilter qf = new QueryWrapperFilter(query);
123     return new ChainedFilter(new Filter[] {qf, filter},
124                              ChainedFilter.AND);
125   }
126
127   public DistanceFilter getDistanceFilter() {
128     return distanceFilter;
129   }
130     
131   public Query getQuery(Query query){
132     return new ConstantScoreQuery(getFilter(query));
133   }
134   
135   public double getLat() {
136     return lat;
137   }
138
139   public double getLng() {
140     return lng;
141   }
142
143   public double getMiles() {
144     return miles;
145   }
146     
147   @Override
148   public String toString() {
149     return "DistanceQuery lat: " + lat + " lng: " + lng + " miles: "+ miles;
150   }
151 }