github.com/balzaczyy/golucene@v0.0.0-20151210033525-d0be9ee89713/core/search/weights.go (about) 1 package search 2 3 import ( 4 "github.com/balzaczyy/golucene/core/index" 5 . "github.com/balzaczyy/golucene/core/search/model" 6 "github.com/balzaczyy/golucene/core/util" 7 ) 8 9 // search/Weight.java 10 11 /* 12 Expert: calculate query weights and build query scorers. 13 14 The purpose of Weight is to ensure searching does not modify a Qurey, 15 so that a Query instance can be reused. 16 IndexSearcher dependent state of the query should reside in the Weight. 17 AtomicReader dependent state should reside in the Scorer. 18 19 Since Weight creates Scorer instances for a given AtomicReaderContext 20 (scorer()), callers must maintain the relationship between the 21 searcher's top-level IndexReaderCntext and context used to create a 22 Scorer. 23 24 A Weight is used in the following way: 25 1. A Weight is constructed by a top-level query, given a 26 IndexSearcher (Query.createWeight()). 27 2. The valueForNormalizatin() method is called on the Weight to 28 compute the query normalization factor Similarity.queryNorm() of 29 the query clauses contained in the query. 30 3. The query normlaization factor is passed to normalize(). At this 31 point the weighting is complete. 32 4. A Scorer is constructed by scorer(). 33 */ 34 type Weight interface { 35 // An explanation of the score computation for the named document. 36 Explain(*index.AtomicReaderContext, int) (Explanation, error) 37 /** The value for normalization of contained query clauses (e.g. sum of squared weights). */ 38 ValueForNormalization() float32 39 /** Assigns the query normalization factor and boost from parent queries to this. */ 40 Normalize(norm float32, topLevelBoost float32) 41 // Scorer(*index.AtomicReaderContext, util.Bits) (Scorer, error) 42 /** 43 * Returns a {@link Scorer} which scores documents in/out-of order according 44 * to <code>scoreDocsInOrder</code>. 45 * <p> 46 * <b>NOTE:</b> even if <code>scoreDocsInOrder</code> is false, it is 47 * recommended to check whether the returned <code>Scorer</code> indeed scores 48 * documents out of order (i.e., call {@link #scoresDocsOutOfOrder()}), as 49 * some <code>Scorer</code> implementations will always return documents 50 * in-order.<br> 51 * <b>NOTE:</b> null can be returned if no documents will be scored by this 52 * query. 53 */ 54 BulkScorer(*index.AtomicReaderContext, bool, util.Bits) (BulkScorer, error) 55 /** 56 * Returns true iff this implementation scores docs only out of order. This 57 * method is used in conjunction with {@link Collector}'s 58 * {@link Collector#acceptsDocsOutOfOrder() acceptsDocsOutOfOrder} and 59 * {@link #scorer(AtomicReaderContext, boolean, boolean, Bits)} to 60 * create a matching {@link Scorer} instance for a given {@link Collector}, or 61 * vice versa. 62 * <p> 63 * <b>NOTE:</b> the default implementation returns <code>false</code>, i.e. 64 * the <code>Scorer</code> scores documents in-order. 65 */ 66 IsScoresDocsOutOfOrder() bool // usually false 67 } 68 69 type WeightImplSPI interface { 70 Scorer(*index.AtomicReaderContext, util.Bits) (Scorer, error) 71 } 72 73 type WeightImpl struct { 74 spi WeightImplSPI 75 } 76 77 func newWeightImpl(spi WeightImplSPI) *WeightImpl { 78 return &WeightImpl{spi} 79 } 80 81 func (w *WeightImpl) BulkScorer(ctx *index.AtomicReaderContext, 82 scoreDocsInOrder bool, acceptDoc util.Bits) (bs BulkScorer, err error) { 83 84 var scorer Scorer 85 if scorer, err = w.spi.Scorer(ctx, acceptDoc); err != nil { 86 return nil, err 87 } else if scorer == nil { 88 // no docs match 89 return nil, nil 90 } 91 92 // this impl always scores docs in order, so we can ignore scoreDocsInOrder: 93 return newDefaultScorer(scorer), nil 94 } 95 96 /* Just wraps a Scorer and performs top scoring using it. */ 97 type DefaultBulkScorer struct { 98 *BulkScorerImpl 99 scorer Scorer 100 } 101 102 func newDefaultScorer(scorer Scorer) *DefaultBulkScorer { 103 assert(scorer != nil) 104 ans := &DefaultBulkScorer{scorer: scorer} 105 ans.BulkScorerImpl = newBulkScorer(ans) 106 return ans 107 } 108 109 func (s *DefaultBulkScorer) ScoreAndCollectUpto(collector Collector, max int) (ok bool, err error) { 110 collector.SetScorer(s.scorer) 111 if max == NO_MORE_DOCS { 112 return false, s.scoreAll(collector, s.scorer) 113 } 114 doc := s.scorer.DocId() 115 if doc < 0 { 116 if doc, err = s.scorer.NextDoc(); err != nil { 117 return false, err 118 } 119 } 120 return s.scoreRange(collector, s.scorer, doc, max) 121 } 122 123 func (s *DefaultBulkScorer) scoreRange(collector Collector, 124 scorer Scorer, currentDoc, end int) (bool, error) { 125 126 var err error 127 for currentDoc < end && err == nil { 128 if err = collector.Collect(currentDoc); err == nil { 129 currentDoc, err = scorer.NextDoc() 130 } 131 } 132 return currentDoc != NO_MORE_DOCS, err 133 } 134 135 func (s *DefaultBulkScorer) scoreAll(collector Collector, scorer Scorer) (err error) { 136 var doc int 137 for doc, err = scorer.NextDoc(); doc != NO_MORE_DOCS && err == nil; doc, err = scorer.NextDoc() { 138 err = collector.Collect(doc) 139 } 140 return 141 }