ElasticSearch-specific query parameters.
| 116 | |
| 117 | |
| 118 | class SearchQueryParser(QueryParser): |
| 119 | """ElasticSearch-specific query parameters.""" |
| 120 | |
| 121 | # Facets with known, limited cardinality: |
| 122 | SMALL_FACETS = ("schema", "schemata", "collection_id", "countries", "languages") |
| 123 | |
| 124 | def __init__(self, args, authz, limit=None): |
| 125 | super(SearchQueryParser, self).__init__(args, authz, limit=limit) |
| 126 | self.offset = min(MAX_PAGE, self.offset) |
| 127 | if (self.limit + self.offset) > MAX_PAGE: |
| 128 | self.limit = max(0, MAX_PAGE - self.offset) |
| 129 | |
| 130 | # Set of field names to facet by (i.e. include the count of distinct |
| 131 | # values in the result set). These must match 'keyword' fields in the |
| 132 | # index. |
| 133 | self.facet_names = set(self.getlist("facet")) |
| 134 | |
| 135 | # Query to use for highlighting, defaults to the search query |
| 136 | self.highlight_text = self.get("highlight_text", self.text) |
| 137 | # Include highlighted fragments of matching text in the result. |
| 138 | self.highlight = self.getbool("highlight", False) |
| 139 | self.highlight = self.highlight and SETTINGS.RESULT_HIGHLIGHT |
| 140 | self.highlight = self.highlight and self.highlight_text |
| 141 | # Length of each snippet in characters |
| 142 | self.highlight_length = self.getint("highlight_length", 120) |
| 143 | # Number of snippets per document, 0 = return full document text. |
| 144 | self.highlight_count = self.getint("highlight_count", 3) |
| 145 | # By default, the maximum number of characters analyzed for a highlight |
| 146 | # request is bounded by the value defined in the |
| 147 | # index.highlight.max_analyzed_offset setting (1000000 by default), |
| 148 | # and when the number of characters exceeds this limit an error is |
| 149 | # returned. By setting `max_analyzed_offset` to a non-negative value |
| 150 | # lower than `index.highlight.max_analyzed_offset`, the highlighting |
| 151 | # stops at this defined maximum limit, and the rest of the text is not |
| 152 | # processed, thus not highlighted and no error is returned. |
| 153 | self.max_highlight_analyzed_offset = self.getint( |
| 154 | "max_highlight_analyzed_offset", 999999 |
| 155 | ) |
| 156 | |
| 157 | def get_facet_size(self, name): |
| 158 | """Number of distinct values to be included (i.e. top N).""" |
| 159 | facet_size = self.getint("facet_size:%s" % name, 20) |
| 160 | # Added to mitigate a DDoS by scripted facet bots (2020-11-24): |
| 161 | if not self.authz.logged_in and name not in self.SMALL_FACETS: |
| 162 | facet_size = min(50, facet_size) |
| 163 | return facet_size |
| 164 | |
| 165 | def get_facet_total(self, name): |
| 166 | """Flag to perform a count of the total number of distinct values.""" |
| 167 | if not self.authz.logged_in and name not in self.SMALL_FACETS: |
| 168 | return False |
| 169 | return self.getbool("facet_total:%s" % name, False) |
| 170 | |
| 171 | def get_facet_values(self, name): |
| 172 | """Flag to disable returning actual values (i.e. count only).""" |
| 173 | # Added to mitigate a DDoS by scripted facet bots (2020-11-24): |
| 174 | if self.get_facet_size(name) == 0: |
| 175 | return False |
no outgoing calls