/** * Iterates DocSets to test for equality - slow and for testing purposes only. * * @lucene.internal */ public static boolean equals(DocSet a, DocSet b) { DocIterator iter1 = a.iterator(); DocIterator iter2 = b.iterator(); for (; ; ) { boolean n1 = iter1.hasNext(); boolean n2 = iter2.hasNext(); if (n1 != n2) { return false; } if (!n1) return true; // made it to end int d1 = iter1.nextDoc(); int d2 = iter2.nextDoc(); if (d1 != d2) { return false; } } }
public void iter(DocSet d1, DocSet d2) { // HashDocSet and DocList doesn't iterate in order. if (d1 instanceof HashDocSet || d2 instanceof HashDocSet || d1 instanceof DocList || d2 instanceof DocList) return; DocIterator i1 = d1.iterator(); DocIterator i2 = d2.iterator(); assert (i1.hasNext() == i2.hasNext()); for (; ; ) { boolean b1 = i1.hasNext(); boolean b2 = i2.hasNext(); assertEquals(b1, b2); if (!b1) break; assertEquals(i1.nextDoc(), i2.nextDoc()); } }
protected void doFieldSortValues(ResponseBuilder rb, SolrIndexSearcher searcher) throws IOException { SolrQueryRequest req = rb.req; SolrQueryResponse rsp = rb.rsp; // The query cache doesn't currently store sort field values, and SolrIndexSearcher doesn't // currently have an option to return sort field values. Because of this, we // take the documents given and re-derive the sort values. boolean fsv = req.getParams().getBool(ResponseBuilder.FIELD_SORT_VALUES, false); if (fsv) { Sort sort = rb.getSortSpec().getSort(); SortField[] sortFields = sort == null ? new SortField[] {SortField.FIELD_SCORE} : sort.getSort(); NamedList sortVals = new NamedList(); // order is important for the sort fields Field field = new Field("dummy", "", Field.Store.YES, Field.Index.NO); // a dummy Field SolrIndexReader reader = searcher.getReader(); SolrIndexReader[] readers = reader.getLeafReaders(); SolrIndexReader subReader = reader; if (readers.length == 1) { // if there is a single segment, use that subReader and avoid looking up each time subReader = readers[0]; readers = null; } int[] offsets = reader.getLeafOffsets(); for (SortField sortField : sortFields) { int type = sortField.getType(); if (type == SortField.SCORE || type == SortField.DOC) continue; FieldComparator comparator = null; FieldComparator comparators[] = (readers == null) ? null : new FieldComparator[readers.length]; String fieldname = sortField.getField(); FieldType ft = fieldname == null ? null : req.getSchema().getFieldTypeNoEx(fieldname); DocList docList = rb.getResults().docList; ArrayList<Object> vals = new ArrayList<Object>(docList.size()); DocIterator it = rb.getResults().docList.iterator(); int offset = 0; int idx = 0; while (it.hasNext()) { int doc = it.nextDoc(); if (readers != null) { idx = SolrIndexReader.readerIndex(doc, offsets); subReader = readers[idx]; offset = offsets[idx]; comparator = comparators[idx]; } if (comparator == null) { comparator = sortField.getComparator(1, 0); comparator = comparator.setNextReader(subReader, offset); if (comparators != null) comparators[idx] = comparator; } doc -= offset; // adjust for what segment this is in comparator.copy(0, doc); Object val = comparator.value(0); // Sortable float, double, int, long types all just use a string // comparator. For these, we need to put the type into a readable // format. One reason for this is that XML can't represent all // string values (or even all unicode code points). // indexedToReadable() should be a no-op and should // thus be harmless anyway (for all current ways anyway) if (val instanceof String) { field.setValue((String) val); val = ft.toObject(field); } // Must do the same conversion when sorting by a // String field in Lucene, which returns the terms // data as BytesRef: if (val instanceof BytesRef) { field.setValue(((BytesRef) val).utf8ToString()); val = ft.toObject(field); } vals.add(val); } sortVals.add(fieldname, vals); } rsp.add("sort_values", sortVals); } }
@Override public Query parse() throws ParseException { // this will combine the results that are found for each // administrative level BooleanQuery allQuery = new BooleanQuery(); // attempt to create a query on city (low level administrative division) String city = localParams.get(CITY); if (city != null) { city = city.toLowerCase(); SchemaField nameField = req.getSchema().getField(NAME_FIELD); FieldType nameFieldType = nameField.getType(); Query cityQuery = nameFieldType.getFieldQuery(this, nameField, city); allQuery.add(cityQuery, Occur.MUST); } // attempt to create a query on state (mid level administrative division) String state = localParams.get(STATE); if (state != null) { state = state.toLowerCase(); SchemaField stateField = req.getSchema().getField(STATE_FIELD); FieldType stateFieldType = stateField.getType(); Query stateQuery = stateFieldType.getFieldQuery(this, stateField, state); allQuery.add(stateQuery, Occur.MUST); } // attempt to create a query on city (high level administrative division) String country = localParams.get(COUNTRY); if (country != null) { country = country.toLowerCase(); SchemaField countryField = req.getSchema().getField(COUNTRY_FIELD); FieldType countryFieldType = countryField.getType(); Query countryQuery = countryFieldType.getFieldQuery(this, countryField, country); allQuery.add(countryQuery, Occur.MUST); } String latitude = null; String longitude = null; // no location provided, computer user's location via reverse-ip lookup if (allQuery.getClauses().length == 0) { HttpServletRequest httpreq = req.getHttpServletRequest(); String ip = httpreq.getRemoteAddr(); LatLng currLoc = geoTargeter.getCurrentLocation(ip); if (currLoc != null) { latitude = Double.toString(currLoc.getLat()); longitude = Double.toString(currLoc.getLng()); } } else { SolrIndexSearcher searcher = req.getSearcher(); Document geocodeDoc = null; try { Sort s = new Sort(new SortField(POPULATION_FIELD, SortField.LONG, true)); DocList docs = searcher.getDocList(allQuery, new ArrayList<Query>(), s, 0, 1, 0); if (docs == null) return query; DocIterator iter = docs.iterator(); int geocodeDocId = iter.nextDoc(); geocodeDoc = searcher.doc(geocodeDocId); } catch (Exception e) { e.printStackTrace(); return query; } latitude = geocodeDoc.get("latitude"); longitude = geocodeDoc.get("longitude"); } // combine the spatial and free-text queries BooleanQuery finalQuery = new BooleanQuery(); // if no location is provided and user's location cannot be determined, // do not search location if (latitude != null && longitude != null) { String distance = localParams.get(DISTANCE); try { Double.parseDouble(distance); } catch (Exception e) { distance = SEARCH_RADIUS; } SpatialFilterQParserPlugin spatialFilter = new SpatialFilterQParserPlugin(); ModifiableSolrParams spatialParams = new ModifiableSolrParams(); spatialParams.add(SpatialParams.POINT, latitude + "," + longitude); spatialParams.add(SpatialParams.DISTANCE, distance); spatialParams.add(CommonParams.FL, LOCATION_FIELD); Query spatialQuery = spatialFilter.createParser(qstr, spatialParams, spatialParams, req).parse(); finalQuery.add(spatialQuery, Occur.MUST); } // get results from default LuceneQParser Query defQuery = new LuceneQParserPlugin().createParser(qstr, localParams, params, req).parse(); finalQuery.add(defQuery, Occur.MUST); return finalQuery; }
public void handleMergeFields(ResponseBuilder rb, SolrIndexSearcher searcher) throws IOException { SolrQueryRequest req = rb.req; SolrQueryResponse rsp = rb.rsp; // The query cache doesn't currently store sort field values, and SolrIndexSearcher doesn't // currently have an option to return sort field values. Because of this, we // take the documents given and re-derive the sort values. // // TODO: See SOLR-5595 boolean fsv = req.getParams().getBool(ResponseBuilder.FIELD_SORT_VALUES, false); if (fsv) { NamedList<Object[]> sortVals = new NamedList<>(); // order is important for the sort fields IndexReaderContext topReaderContext = searcher.getTopReaderContext(); List<LeafReaderContext> leaves = topReaderContext.leaves(); LeafReaderContext currentLeaf = null; if (leaves.size() == 1) { // if there is a single segment, use that subReader and avoid looking up each time currentLeaf = leaves.get(0); leaves = null; } DocList docList = rb.getResults().docList; // sort ids from lowest to highest so we can access them in order int nDocs = docList.size(); final long[] sortedIds = new long[nDocs]; final float[] scores = new float[nDocs]; // doc scores, parallel to sortedIds DocList docs = rb.getResults().docList; DocIterator it = docs.iterator(); for (int i = 0; i < nDocs; i++) { sortedIds[i] = (((long) it.nextDoc()) << 32) | i; scores[i] = docs.hasScores() ? it.score() : Float.NaN; } // sort ids and scores together new InPlaceMergeSorter() { @Override protected void swap(int i, int j) { long tmpId = sortedIds[i]; float tmpScore = scores[i]; sortedIds[i] = sortedIds[j]; scores[i] = scores[j]; sortedIds[j] = tmpId; scores[j] = tmpScore; } @Override protected int compare(int i, int j) { return Long.compare(sortedIds[i], sortedIds[j]); } }.sort(0, sortedIds.length); SortSpec sortSpec = rb.getSortSpec(); Sort sort = searcher.weightSort(sortSpec.getSort()); SortField[] sortFields = sort == null ? new SortField[] {SortField.FIELD_SCORE} : sort.getSort(); List<SchemaField> schemaFields = sortSpec.getSchemaFields(); for (int fld = 0; fld < schemaFields.size(); fld++) { SchemaField schemaField = schemaFields.get(fld); FieldType ft = null == schemaField ? null : schemaField.getType(); SortField sortField = sortFields[fld]; SortField.Type type = sortField.getType(); // :TODO: would be simpler to always serialize every position of SortField[] if (type == SortField.Type.SCORE || type == SortField.Type.DOC) continue; FieldComparator<?> comparator = null; LeafFieldComparator leafComparator = null; Object[] vals = new Object[nDocs]; int lastIdx = -1; int idx = 0; for (int i = 0; i < sortedIds.length; ++i) { long idAndPos = sortedIds[i]; float score = scores[i]; int doc = (int) (idAndPos >>> 32); int position = (int) idAndPos; if (leaves != null) { idx = ReaderUtil.subIndex(doc, leaves); currentLeaf = leaves.get(idx); if (idx != lastIdx) { // we switched segments. invalidate comparator. comparator = null; } } if (comparator == null) { comparator = sortField.getComparator(1, 0); leafComparator = comparator.getLeafComparator(currentLeaf); } doc -= currentLeaf.docBase; // adjust for what segment this is in leafComparator.setScorer(new FakeScorer(doc, score)); leafComparator.copy(0, doc); Object val = comparator.value(0); if (null != ft) val = ft.marshalSortValue(val); vals[position] = val; } sortVals.add(sortField.getField(), vals); } rsp.add("merge_values", sortVals); } }