@@ -16,6 +16,7 @@ namespace search::queryeval {
1616namespace {
1717
1818using search::fef::TermFieldMatchDataArray;
19+ using search::fef::TermFieldMatchDataPosition;
1920using search::fef::TermFieldMatchDataPositionKey;
2021
2122template <typename T>
@@ -32,6 +33,16 @@ void setup_fields(uint32_t window, const IElementGapInspector& element_gap_inspe
3233 }
3334}
3435
36+ TermFieldMatchDataPositionKey
37+ calc_window_end_pos (const TermFieldMatchDataPosition& pos, uint32_t window, std::optional<uint32_t > element_gap)
38+ {
39+ if (!element_gap.has_value () || pos.getElementLen () + element_gap.value () > pos.getPosition () + window) {
40+ return { pos.getElementId (), pos.getPosition () + window };
41+ } else {
42+ return { pos.getElementId () + 1 , pos.getPosition () + window - pos.getElementLen () - element_gap.value () };
43+ }
44+ }
45+
3546} // namespace search::queryeval::<unnamed>
3647
3748NearSearchBase::NearSearchBase (Children terms,
@@ -153,8 +164,15 @@ struct PosIter {
153164struct Iterators
154165{
155166 vespalib::PriorityQueue<PosIter> _queue;
156- TermFieldMatchDataPositionKey _maxOcc;
167+ TermFieldMatchDataPositionKey _maxOcc;
168+ std::optional<uint32_t > _element_gap;
157169
170+ Iterators (std::optional<uint32_t > element_gap)
171+ : _queue(),
172+ _maxOcc (),
173+ _element_gap(element_gap)
174+ {
175+ }
158176 void update (TermFieldMatchDataPositionKey occ)
159177 {
160178 if (_queue.size () == 1 || _maxOcc < occ) { _maxOcc = occ; }
@@ -173,8 +191,7 @@ struct Iterators
173191 bool match (uint32_t window) {
174192 for (;;) {
175193 PosIter &front = _queue.front ();
176- TermFieldMatchDataPositionKey lastAllowed = *front.curPos ;
177- lastAllowed.setPosition (front.curPos ->getPosition () + window);
194+ auto lastAllowed = calc_window_end_pos (*front.curPos , window, _element_gap);
178195
179196 if (!(lastAllowed < _maxOcc)) {
180197 return true ;
@@ -184,8 +201,7 @@ struct Iterators
184201 if (front.curPos == front.endPos ) {
185202 return false ;
186203 }
187- lastAllowed = *front.curPos ;
188- lastAllowed.setPosition (front.curPos ->getPosition () + window);
204+ lastAllowed = calc_window_end_pos (*front.curPos , window, _element_gap);
189205 } while (lastAllowed < _maxOcc);
190206
191207 update (*front.curPos );
@@ -199,7 +215,7 @@ struct Iterators
199215bool
200216NearSearch::Matcher::match (uint32_t docId)
201217{
202- Iterators pos;
218+ Iterators pos ( get_element_gap ()) ;
203219 for (uint32_t i = 0 , len = inputs ().size (); i < len; ++i) {
204220 const search::fef::TermFieldMatchData *term = inputs ()[i];
205221 if (term->getDocId () != docId || term->begin () == term->end ()) {
@@ -263,15 +279,14 @@ ONearSearch::Matcher::match(uint32_t docId)
263279 // Look for match for every occurrence of the first term.
264280 for ( ; pos[0 ] != inputs ()[0 ]->end (); ++pos[0 ]) {
265281 TermFieldMatchDataPositionKey firstTermPos = *pos[0 ];
266- lastAllowed = firstTermPos;
267- lastAllowed.setPosition (firstTermPos.getPosition () + remain);
282+ lastAllowed = calc_window_end_pos (*pos[0 ], remain, get_element_gap ());
268283 if (lastAllowed < curTermPos) {
269284 // if we already know that we must seek onwards:
270285 continue ;
271286 }
272287 prevTermPos = firstTermPos;
273- LOG (spam, " Looking for match in window [%d, %d]." ,
274- firstTermPos.getPosition (), lastAllowed.getPosition ());
288+ LOG (spam, " Looking for match in window [%d:%d, %d: %d]." ,
289+ firstTermPos.getElementId (), firstTermPos. getPosition (), lastAllowed. getElementId (), lastAllowed.getPosition ());
275290 for (uint32_t i = 1 ; i < numTerms; ++i) {
276291 LOG (spam, " Forwarding iterator for term %d beyond %d." , i, prevTermPos.getPosition ());
277292 while (pos[i] != inputs ()[i]->end () && !(prevTermPos < *pos[i])) {
0 commit comments