@Override protected boolean doEquals(Object obj) { InternalTopHits other = (InternalTopHits) obj; if (from != other.from) return false; if (size != other.size) return false; if (topDocs.totalHits != other.topDocs.totalHits) return false; if (topDocs.scoreDocs.length != other.topDocs.scoreDocs.length) return false; for (int d = 0; d < topDocs.scoreDocs.length; d++) { ScoreDoc thisDoc = topDocs.scoreDocs[d]; ScoreDoc otherDoc = other.topDocs.scoreDocs[d]; if (thisDoc.doc != otherDoc.doc) return false; if (Double.compare(thisDoc.score, otherDoc.score) != 0) return false; if (thisDoc.shardIndex != otherDoc.shardIndex) return false; if (thisDoc instanceof FieldDoc) { if (false == (otherDoc instanceof FieldDoc)) return false; FieldDoc thisFieldDoc = (FieldDoc) thisDoc; FieldDoc otherFieldDoc = (FieldDoc) otherDoc; if (thisFieldDoc.fields.length != otherFieldDoc.fields.length) return false; for (int f = 0; f < thisFieldDoc.fields.length; f++) { if (false == thisFieldDoc.fields[f].equals(otherFieldDoc.fields[f])) return false; } } } return searchHits.equals(other.searchHits); }
@Override protected int doHashCode() { int hashCode = from; hashCode = 31 * hashCode + size; hashCode = 31 * hashCode + topDocs.totalHits; for (int d = 0; d < topDocs.scoreDocs.length; d++) { ScoreDoc doc = topDocs.scoreDocs[d]; hashCode = 31 * hashCode + doc.doc; hashCode = 31 * hashCode + Float.floatToIntBits(doc.score); hashCode = 31 * hashCode + doc.shardIndex; if (doc instanceof FieldDoc) { FieldDoc fieldDoc = (FieldDoc) doc; hashCode = 31 * hashCode + Arrays.hashCode(fieldDoc.fields); } } hashCode = 31 * hashCode + searchHits.hashCode(); return hashCode; }
@Override public void writeTo(StreamOutput out) throws IOException { super.writeTo(out); out.writeLong(id); out.writeVInt(size); for (int i = 0; i < size; i++) { out.writeVInt(docIds[i]); } if (lastEmittedDoc == null) { out.writeByte((byte) 0); } else if (lastEmittedDoc instanceof FieldDoc) { out.writeByte((byte) 1); Lucene.writeFieldDoc(out, (FieldDoc) lastEmittedDoc); } else { out.writeByte((byte) 2); Lucene.writeScoreDoc(out, lastEmittedDoc); } }
@Override protected void assertAvgScoreMode(Query parentFilter, IndexSearcher searcher) throws IOException { MultiValueMode sortMode = MultiValueMode.AVG; Query childFilter = Queries.not(parentFilter); XFieldComparatorSource nestedComparatorSource = createFieldComparator("field2", sortMode, -127, createNested(searcher, parentFilter, childFilter)); Query query = new ToParentBlockJoinQuery(new ConstantScoreQuery(childFilter), new QueryBitSetProducer(parentFilter), ScoreMode.None); Sort sort = new Sort(new SortField("field2", nestedComparatorSource)); TopDocs topDocs = searcher.search(query, 5, sort); assertThat(topDocs.totalHits, equalTo(7)); assertThat(topDocs.scoreDocs.length, equalTo(5)); assertThat(topDocs.scoreDocs[0].doc, equalTo(11)); assertThat(((Number) ((FieldDoc) topDocs.scoreDocs[0]).fields[0]).intValue(), equalTo(2)); assertThat(topDocs.scoreDocs[1].doc, equalTo(7)); assertThat(((Number) ((FieldDoc) topDocs.scoreDocs[1]).fields[0]).intValue(), equalTo(2)); assertThat(topDocs.scoreDocs[2].doc, equalTo(3)); assertThat(((Number) ((FieldDoc) topDocs.scoreDocs[2]).fields[0]).intValue(), equalTo(3)); assertThat(topDocs.scoreDocs[3].doc, equalTo(15)); assertThat(((Number) ((FieldDoc) topDocs.scoreDocs[3]).fields[0]).intValue(), equalTo(3)); assertThat(topDocs.scoreDocs[4].doc, equalTo(19)); assertThat(((Number) ((FieldDoc) topDocs.scoreDocs[4]).fields[0]).intValue(), equalTo(3)); }
protected void assertAvgScoreMode(Query parentFilter, IndexSearcher searcher, IndexFieldData.XFieldComparatorSource innerFieldComparator) throws IOException { MultiValueMode sortMode = MultiValueMode.AVG; Query childFilter = Queries.not(parentFilter); XFieldComparatorSource nestedComparatorSource = createFieldComparator("field2", sortMode, -127, createNested(searcher, parentFilter, childFilter)); Query query = new ToParentBlockJoinQuery(new ConstantScoreQuery(childFilter), new QueryBitSetProducer(parentFilter), ScoreMode.None); Sort sort = new Sort(new SortField("field2", nestedComparatorSource)); TopDocs topDocs = searcher.search(query, 5, sort); assertThat(topDocs.totalHits, equalTo(7)); assertThat(topDocs.scoreDocs.length, equalTo(5)); assertThat(topDocs.scoreDocs[0].doc, equalTo(11)); assertThat(((Number) ((FieldDoc) topDocs.scoreDocs[0]).fields[0]).intValue(), equalTo(2)); assertThat(topDocs.scoreDocs[1].doc, equalTo(7)); assertThat(((Number) ((FieldDoc) topDocs.scoreDocs[1]).fields[0]).intValue(), equalTo(2)); assertThat(topDocs.scoreDocs[2].doc, equalTo(3)); assertThat(((Number) ((FieldDoc) topDocs.scoreDocs[2]).fields[0]).intValue(), equalTo(3)); assertThat(topDocs.scoreDocs[3].doc, equalTo(15)); assertThat(((Number) ((FieldDoc) topDocs.scoreDocs[3]).fields[0]).intValue(), equalTo(3)); assertThat(topDocs.scoreDocs[4].doc, equalTo(19)); assertThat(((Number) ((FieldDoc) topDocs.scoreDocs[4]).fields[0]).intValue(), equalTo(3)); }
protected void assertAvgScoreMode(Query parentFilter, IndexSearcher searcher) throws IOException { MultiValueMode sortMode = MultiValueMode.AVG; Query childFilter = Queries.not(parentFilter); XFieldComparatorSource nestedComparatorSource = createFieldComparator("field2", sortMode, -127, createNested(searcher, parentFilter, childFilter)); Query query = new ToParentBlockJoinQuery(new ConstantScoreQuery(childFilter), new QueryBitSetProducer(parentFilter), ScoreMode.None); Sort sort = new Sort(new SortField("field2", nestedComparatorSource)); TopDocs topDocs = searcher.search(query, 5, sort); assertThat(topDocs.totalHits, equalTo(7)); assertThat(topDocs.scoreDocs.length, equalTo(5)); assertThat(topDocs.scoreDocs[0].doc, equalTo(11)); assertThat(((Number) ((FieldDoc) topDocs.scoreDocs[0]).fields[0]).intValue(), equalTo(2)); assertThat(topDocs.scoreDocs[1].doc, equalTo(3)); assertThat(((Number) ((FieldDoc) topDocs.scoreDocs[1]).fields[0]).intValue(), equalTo(3)); assertThat(topDocs.scoreDocs[2].doc, equalTo(7)); assertThat(((Number) ((FieldDoc) topDocs.scoreDocs[2]).fields[0]).intValue(), equalTo(3)); assertThat(topDocs.scoreDocs[3].doc, equalTo(15)); assertThat(((Number) ((FieldDoc) topDocs.scoreDocs[3]).fields[0]).intValue(), equalTo(3)); assertThat(topDocs.scoreDocs[4].doc, equalTo(19)); assertThat(((Number) ((FieldDoc) topDocs.scoreDocs[4]).fields[0]).intValue(), equalTo(4)); }
public void testSortValues() throws Exception { Directory dir = new RAMDirectory(); IndexWriter indexWriter = new IndexWriter(dir, new IndexWriterConfig(Lucene.STANDARD_ANALYZER)); for (int i = 0; i < 10; i++) { Document document = new Document(); String text = new String(new char[]{(char) (97 + i), (char) (97 + i)}); document.add(new TextField("str", text, Field.Store.YES)); document.add(new SortedDocValuesField("str", new BytesRef(text))); indexWriter.addDocument(document); } IndexReader reader = SlowCompositeReaderWrapper.wrap(DirectoryReader.open(indexWriter)); IndexSearcher searcher = new IndexSearcher(reader); TopFieldDocs docs = searcher.search(new MatchAllDocsQuery(), 10, new Sort(new SortField("str", SortField.Type.STRING))); for (int i = 0; i < 10; i++) { FieldDoc fieldDoc = (FieldDoc) docs.scoreDocs[i]; assertThat((BytesRef) fieldDoc.fields[0], equalTo(new BytesRef(new String(new char[]{(char) (97 + i), (char) (97 + i)})))); } }
@Nullable @Override public Row apply(@Nullable ScoreDoc input) { if (input == null) { return null; } FieldDoc fieldDoc = (FieldDoc) input; scorer.score(fieldDoc.score); for (OrderByCollectorExpression orderByCollectorExpression : orderByCollectorExpressions) { orderByCollectorExpression.setNextFieldDoc(fieldDoc); } List<LeafReaderContext> leaves = indexReader.leaves(); int readerIndex = ReaderUtil.subIndex(fieldDoc.doc, leaves); LeafReaderContext subReaderContext = leaves.get(readerIndex); int subDoc = fieldDoc.doc - subReaderContext.docBase; for (LuceneCollectorExpression<?> expression : expressions) { expression.setNextReader(subReaderContext); expression.setNextDocId(subDoc); } return inputRow; }
private List<LindenHit> parseLindenHits(ScoreDoc[] hits) throws IOException { List<LindenHit> lindenHits = new ArrayList<>(); String idFieldName = config.getSchema().getId(); for (ScoreDoc hit : hits) { LindenHit lindenHit = new LindenHit(); if (Double.isNaN(hit.score)) { // get score for cluster result merge if (sortScoreFieldPos != -1) { lindenHit.setScore(Double.valueOf(((FieldDoc) hit).fields[sortScoreFieldPos].toString())); } else { lindenHit.setScore(1); } } else { lindenHit.setScore(hit.score); } String id = LindenUtil.getFieldStringValue(leaves, hit.doc, idFieldName); lindenHit.setId(id); lindenHit = this.parseSpatial(hit.doc, lindenHit); lindenHit = this.parseSort(hit, lindenHit); lindenHit = this.parseSource(hit.doc, lindenHit); lindenHit = this.parseExplain(hit.doc, lindenHit); lindenHits.add(lindenHit); } lindenHits = this.parseSnippets(lindenHits, hits); return lindenHits; }
private LindenHit parseSort(ScoreDoc hit, LindenHit lindenHit) { if (request.isSetSort()) { Map<String, String> fieldMap = new HashMap<>(); for (int i = 0; i < request.getSort().getFields().size(); ++i) { LindenSortField field = request.getSort().getFields().get(i); if (field.type == LindenSortType.SCORE || field.type == LindenSortType.DISTANCE) { continue; } Object value = ((FieldDoc) hit).fields[i]; if (value == null) { continue; } if (field.type == LindenSortType.STRING) { fieldMap.put(field.getName(), ((BytesRef) value).utf8ToString()); } else { fieldMap.put(field.getName(), value.toString()); } } lindenHit.setFields(fieldMap); } return lindenHit; }
@Override public byte[] serialize(final FieldDoc doc) { if (doc == null) { throw new IllegalArgumentException("FieldDoc cannot be null"); } try { final SerializableFieldDoc sFieldDoc = new SerializableFieldDoc(); sFieldDoc.setScore(doc.score); sFieldDoc.setDoc(doc.doc); sFieldDoc.setShardIndex(doc.shardIndex); sFieldDoc.setFields(doc.fields); return mapper.writeValueAsBytes(sFieldDoc); } catch (Exception e) { throw new SerializationException("Unable to serialize FieldDoc due to :" + e.getMessage(), e); } }
@Override public FieldDoc deserialize(byte[] bytes) { if (bytes == null) { throw new IllegalArgumentException("Bytes cannot be null"); } try { final SerializableFieldDoc sFieldDoc = mapper.readValue(bytes, SerializableFieldDoc.class); final FieldDoc fieldDoc = new FieldDoc( sFieldDoc.getDoc(), sFieldDoc.getScore(), sFieldDoc.getFields(), sFieldDoc.getShardIndex() ); return fieldDoc; } catch (Exception e) { throw new SerializationException("Unable to deserialize bytes due to :" + e.getMessage(), e); } }
/** tests the returned sort values are correct */ public void testSortValues() throws Exception { Expression expr = JavascriptCompiler.compile("sqrt(_score)"); SimpleBindings bindings = new SimpleBindings(); bindings.add(new SortField("_score", SortField.Type.SCORE)); Sort sort = new Sort(expr.getSortField(bindings, true)); Query query = new TermQuery(new Term("body", "contents")); TopFieldDocs td = searcher.search(query, null, 3, sort, true, true); for (int i = 0; i < 3; i++) { FieldDoc d = (FieldDoc) td.scoreDocs[i]; float expected = (float) Math.sqrt(d.score); float actual = ((Double)d.fields[0]).floatValue(); assertEquals(expected, actual, CheckHits.explainToleranceDelta(expected, actual)); } }
/** tests same binding used more than once in an expression */ public void testTwoOfSameBinding() throws Exception { Expression expr = JavascriptCompiler.compile("_score + _score"); SimpleBindings bindings = new SimpleBindings(); bindings.add(new SortField("_score", SortField.Type.SCORE)); Sort sort = new Sort(expr.getSortField(bindings, true)); Query query = new TermQuery(new Term("body", "contents")); TopFieldDocs td = searcher.search(query, null, 3, sort, true, true); for (int i = 0; i < 3; i++) { FieldDoc d = (FieldDoc) td.scoreDocs[i]; float expected = 2*d.score; float actual = ((Double)d.fields[0]).floatValue(); assertEquals(expected, actual, CheckHits.explainToleranceDelta(expected, actual)); } }
/** Uses variables with $ */ public void testDollarVariable() throws Exception { Expression expr = JavascriptCompiler.compile("$0+$score"); SimpleBindings bindings = new SimpleBindings(); bindings.add(new SortField("$0", SortField.Type.SCORE)); bindings.add(new SortField("$score", SortField.Type.SCORE)); Sort sort = new Sort(expr.getSortField(bindings, true)); Query query = new TermQuery(new Term("body", "contents")); TopFieldDocs td = searcher.search(query, null, 3, sort, true, true); for (int i = 0; i < 3; i++) { FieldDoc d = (FieldDoc) td.scoreDocs[i]; float expected = 2*d.score; float actual = ((Double)d.fields[0]).floatValue(); assertEquals(expected, actual, CheckHits.explainToleranceDelta(expected, actual)); } }
/** tests expression referring to another expression */ public void testExpressionRefersToExpression() throws Exception { Expression expr1 = JavascriptCompiler.compile("_score"); Expression expr2 = JavascriptCompiler.compile("2*expr1"); SimpleBindings bindings = new SimpleBindings(); bindings.add(new SortField("_score", SortField.Type.SCORE)); bindings.add("expr1", expr1); Sort sort = new Sort(expr2.getSortField(bindings, true)); Query query = new TermQuery(new Term("body", "contents")); TopFieldDocs td = searcher.search(query, null, 3, sort, true, true); for (int i = 0; i < 3; i++) { FieldDoc d = (FieldDoc) td.scoreDocs[i]; float expected = 2*d.score; float actual = ((Double)d.fields[0]).floatValue(); assertEquals(expected, actual, CheckHits.explainToleranceDelta(expected, actual)); } }
private void doTestLotsOfBindings(int n) throws Exception { SimpleBindings bindings = new SimpleBindings(); StringBuilder sb = new StringBuilder(); for (int i = 0; i < n; i++) { if (i > 0) { sb.append("+"); } sb.append("x" + i); bindings.add(new SortField("x" + i, SortField.Type.SCORE)); } Expression expr = JavascriptCompiler.compile(sb.toString()); Sort sort = new Sort(expr.getSortField(bindings, true)); Query query = new TermQuery(new Term("body", "contents")); TopFieldDocs td = searcher.search(query, null, 3, sort, true, true); for (int i = 0; i < 3; i++) { FieldDoc d = (FieldDoc) td.scoreDocs[i]; float expected = n*d.score; float actual = ((Double)d.fields[0]).floatValue(); assertEquals(expected, actual, CheckHits.explainToleranceDelta(expected, actual)); } }
/** * Search, sorting by {@link Sort}, and computing * drill down and sideways counts. */ public DrillSidewaysResult search(DrillDownQuery query, Filter filter, FieldDoc after, int topN, Sort sort, boolean doDocScores, boolean doMaxScore) throws IOException { if (filter != null) { query = new DrillDownQuery(config, filter, query); } if (sort != null) { int limit = searcher.getIndexReader().maxDoc(); if (limit == 0) { limit = 1; // the collector does not alow numHits = 0 } topN = Math.min(topN, limit); final TopFieldCollector hitCollector = TopFieldCollector.create(sort, topN, after, true, doDocScores, doMaxScore, true); DrillSidewaysResult r = search(query, hitCollector); return new DrillSidewaysResult(r.facets, hitCollector.topDocs()); } else { return search(after, query, topN); } }
public static void assertEquals(TopDocs expected, TopDocs actual) { Assert.assertEquals("wrong total hits", expected.totalHits, actual.totalHits); Assert.assertEquals("wrong maxScore", expected.getMaxScore(), actual.getMaxScore(), 0.0); Assert.assertEquals("wrong hit count", expected.scoreDocs.length, actual.scoreDocs.length); for(int hitIDX=0;hitIDX<expected.scoreDocs.length;hitIDX++) { final ScoreDoc expectedSD = expected.scoreDocs[hitIDX]; final ScoreDoc actualSD = actual.scoreDocs[hitIDX]; Assert.assertEquals("wrong hit docID", expectedSD.doc, actualSD.doc); Assert.assertEquals("wrong hit score", expectedSD.score, actualSD.score, 0.0); if (expectedSD instanceof FieldDoc) { Assert.assertTrue(actualSD instanceof FieldDoc); Assert.assertArrayEquals("wrong sort field values", ((FieldDoc) expectedSD).fields, ((FieldDoc) actualSD).fields); } else { Assert.assertFalse(actualSD instanceof FieldDoc); } } }
/** * {@inheritDoc} */ @Override public void process(ResponseBuilder rb, ShardRequest shardRequest) { boolean returnScores = (rb.getFieldFlags() & SolrIndexSearcher.GET_SCORES) != 0; ShardResponse srsp = shardRequest.responses.get(0); SolrDocumentList docs = (SolrDocumentList)srsp.getSolrResponse().getResponse().get("response"); String uniqueIdFieldName = rb.req.getSchema().getUniqueKeyField().getName(); for (SolrDocument doc : docs) { Object id = doc.getFieldValue(uniqueIdFieldName).toString(); ShardDoc shardDoc = rb.resultIds.get(id); FieldDoc fieldDoc = (FieldDoc) shardDoc; if (shardDoc != null) { if (returnScores && !Float.isNaN(fieldDoc.score)) { doc.setField("score", fieldDoc.score); } rb.retrievedDocuments.put(id, doc); } } }
/** * Search, sorting by {@link Sort}, and computing * drill down and sideways counts. */ public DrillSidewaysResult search(DrillDownQuery query, Filter filter, FieldDoc after, int topN, Sort sort, boolean doDocScores, boolean doMaxScore, FacetSearchParams fsp) throws IOException { if (filter != null) { query = new DrillDownQuery(filter, query); } if (sort != null) { final TopFieldCollector hitCollector = TopFieldCollector.create(sort, Math.min(topN, searcher.getIndexReader().maxDoc()), after, true, doDocScores, doMaxScore, true); DrillSidewaysResult r = new DrillSideways(searcher, taxoReader).search(query, hitCollector, fsp); r.hits = hitCollector.topDocs(); return r; } else { return search(after, query, topN, fsp); } }
/** * Search, sorting by {@link Sort}, and computing * drill down and sideways counts. */ public DrillSidewaysResult search(DrillDownQuery query, Filter filter, FieldDoc after, int topN, Sort sort, boolean doDocScores, boolean doMaxScore, FacetSearchParams fsp) throws IOException { if (filter != null) { query = new DrillDownQuery(filter, query); } if (sort != null) { int limit = searcher.getIndexReader().maxDoc(); if (limit == 0) { limit = 1; // the collector does not alow numHits = 0 } topN = Math.min(topN, limit); final TopFieldCollector hitCollector = TopFieldCollector.create(sort, topN, after, true, doDocScores, doMaxScore, true); DrillSidewaysResult r = search(query, hitCollector, fsp); return new DrillSidewaysResult(r.facetResults, hitCollector.topDocs()); } else { return search(after, query, topN, fsp); } }
public void testNeareastRestaurantToWork() throws Exception { Sort sort = new Sort(new SortField("unused", new DistanceComparatorSource(10, 10))); TopFieldDocs docs = searcher.search(query, null, 3, sort); // assertEquals(4, docs.totalHits); // assertEquals(3, docs.scoreDocs.length); // FieldDoc fieldDoc = (FieldDoc) docs.scoreDocs[0]; // assertEquals("(10,10) -> (9,6) = sqrt(17)", new Float(Math.sqrt(17)), fieldDoc.fields[0]); // Document document = searcher.doc(fieldDoc.doc); // assertEquals("Los Betos", document.get("name")); //dumpDocs(sort, docs); }
public static FieldDoc buildFieldDoc(SortAndFormats sort, Object[] values) { if (sort == null || sort.sort.getSort() == null || sort.sort.getSort().length == 0) { throw new IllegalArgumentException("Sort must contain at least one field."); } SortField[] sortFields = sort.sort.getSort(); if (sortFields.length != values.length) { throw new IllegalArgumentException( SEARCH_AFTER.getPreferredName() + " has " + values.length + " value(s) but sort has " + sort.sort.getSort().length + "."); } Object[] fieldValues = new Object[sortFields.length]; for (int i = 0; i < sortFields.length; i++) { SortField sortField = sortFields[i]; DocValueFormat format = sort.formats[i]; if (values[i] != null) { fieldValues[i] = convertValueFromSortField(values[i], sortField, format); } else { fieldValues[i] = null; } } /* * We set the doc id to Integer.MAX_VALUE in order to make sure that the search starts "after" the first document that is equal to * the field values. */ return new FieldDoc(Integer.MAX_VALUE, 0, fieldValues); }
public static FieldDoc readFieldDoc(StreamInput in) throws IOException { Comparable[] cFields = new Comparable[in.readVInt()]; for (int j = 0; j < cFields.length; j++) { byte type = in.readByte(); if (type == 0) { cFields[j] = null; } else if (type == 1) { cFields[j] = in.readString(); } else if (type == 2) { cFields[j] = in.readInt(); } else if (type == 3) { cFields[j] = in.readLong(); } else if (type == 4) { cFields[j] = in.readFloat(); } else if (type == 5) { cFields[j] = in.readDouble(); } else if (type == 6) { cFields[j] = in.readByte(); } else if (type == 7) { cFields[j] = in.readShort(); } else if (type == 8) { cFields[j] = in.readBoolean(); } else if (type == 9) { cFields[j] = in.readBytesRef(); } else { throw new IOException("Can't match type [" + type + "]"); } } return new FieldDoc(in.readVInt(), in.readFloat(), cFields); }
public static void writeFieldDoc(StreamOutput out, FieldDoc fieldDoc) throws IOException { out.writeVInt(fieldDoc.fields.length); for (Object field : fieldDoc.fields) { writeSortValue(out, field); } out.writeVInt(fieldDoc.doc); out.writeFloat(fieldDoc.score); }