forked from apache/solr
-
Notifications
You must be signed in to change notification settings - Fork 0
/
FilterQuery.java
120 lines (104 loc) · 4.1 KB
/
FilterQuery.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.solr.query;
import java.io.IOException;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.search.ConstantScoreQuery;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.MatchNoDocsQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.QueryVisitor;
import org.apache.lucene.search.ScoreMode;
import org.apache.lucene.search.Weight;
import org.apache.solr.search.DocSet;
import org.apache.solr.search.ExtendedQueryBase;
import org.apache.solr.search.SolrIndexSearcher;
public class FilterQuery extends ExtendedQueryBase {
protected final Query q;
public FilterQuery(Query q) {
if (q == null) {
this.q = new MatchNoDocsQuery();
return;
}
this.q = q;
}
@Override
public final void setCache(boolean cache) {
if (cache) {
// because of the special syntax for invoking FilterQuery (i.e., `filter([backing_query])` -- different from
// the normal QParser + localParams syntax) there should be no risk of attempting to set `cache=true`.
throw new IllegalArgumentException(FilterQuery.class + " caches internally and does not support external setCache(true)");
}
}
@Override
public final boolean getCache() {
return false;
// Paradoxically, this _is_ what we want. The FilterQuery wrapper is designed to ensure that its
// inner query always consults the filterCache, regardless of the context in which it's called.
// FilterQuery internally calls SolrIndexSearcher.getDocSet with its _wrapped_ query, so the caching
// happens at that level, and we want _not_ to consult the filterCache with the FilterQuery wrapper
// per se. Allowing `doCache=true` here can result in double-entry in the filterCache (e.g. when
// using `fq=filter({!term f=field v=term})`, or caching separate clauses of a BooleanQuery via
// `fq={!bool should='filter($q1)' should='filter($q2)'}`).
}
public Query getQuery() {
return q;
}
@Override
public int hashCode() {
return q.hashCode() + 0xc0e65615;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof FilterQuery)) return false;
FilterQuery fq = (FilterQuery)obj;
return this.q.equals(fq.q);
}
@Override
public String toString(String field) {
StringBuilder sb = new StringBuilder();
sb.append("filter(");
sb.append(q.toString(""));
sb.append(')');
return sb.toString();
}
@Override
public void visit(QueryVisitor visitor) {
q.visit(visitor);
}
@Override
public Query rewrite(IndexReader reader) throws IOException {
Query newQ = q.rewrite(reader);
if (newQ != q) {
return new FilterQuery(newQ);
} else {
return this;
}
}
@Override
public Weight createWeight(IndexSearcher searcher, ScoreMode scoreMode, float boost) throws IOException {
// SolrRequestInfo reqInfo = SolrRequestInfo.getRequestInfo();
if (!(searcher instanceof SolrIndexSearcher)) {
// delete-by-query won't have SolrIndexSearcher
return new ConstantScoreQuery(q).createWeight(searcher, scoreMode, 1f);
}
SolrIndexSearcher solrSearcher = (SolrIndexSearcher)searcher;
DocSet docs = solrSearcher.getDocSet(q);
// reqInfo.addCloseHook(docs); // needed for off-heap refcounting
return docs.makeQuery().createWeight(searcher, scoreMode, 1f);
}
}