diff options
author | Chayim <chayim@users.noreply.github.com> | 2021-10-25 17:18:27 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-10-25 17:18:27 +0300 |
commit | ddd1496782cc8eb15fca6c9059b2b08a03efe366 (patch) | |
tree | ab907bd2fd2f7cfb951e750de69ea9d4478a5b9c | |
parent | 3946da29d7e451a20289fb6e282516fa24e402af (diff) | |
download | redis-py-ddd1496782cc8eb15fca6c9059b2b08a03efe366.tar.gz |
Adding support for redisearch (#1640)
-rw-r--r-- | redis/commands/redismodules.py | 9 | ||||
-rw-r--r-- | redis/commands/search/__init__.py | 96 | ||||
-rw-r--r-- | redis/commands/search/_util.py | 10 | ||||
-rw-r--r-- | redis/commands/search/aggregation.py | 408 | ||||
-rw-r--r-- | redis/commands/search/commands.py | 704 | ||||
-rw-r--r-- | redis/commands/search/document.py | 16 | ||||
-rw-r--r-- | redis/commands/search/field.py | 94 | ||||
-rw-r--r-- | redis/commands/search/indexDefinition.py | 80 | ||||
-rw-r--r-- | redis/commands/search/query.py | 328 | ||||
-rw-r--r-- | redis/commands/search/querystring.py | 324 | ||||
-rw-r--r-- | redis/commands/search/reducers.py | 178 | ||||
-rw-r--r-- | redis/commands/search/result.py | 75 | ||||
-rw-r--r-- | redis/commands/search/suggestion.py | 54 | ||||
-rw-r--r-- | tasks.py | 1 | ||||
-rw-r--r-- | tests/conftest.py | 15 | ||||
-rw-r--r-- | tests/test_json.py | 50 | ||||
-rw-r--r-- | tests/test_search.py | 1219 | ||||
-rw-r--r-- | tests/testdata/titles.csv | 4861 | ||||
-rwxr-xr-x | tests/testdata/will_play_text.csv.bz2 | bin | 0 -> 2069623 bytes | |||
-rw-r--r-- | tox.ini | 2 |
20 files changed, 8494 insertions, 30 deletions
diff --git a/redis/commands/redismodules.py b/redis/commands/redismodules.py index fb53107..2c9066a 100644 --- a/redis/commands/redismodules.py +++ b/redis/commands/redismodules.py @@ -15,3 +15,12 @@ class RedisModuleCommands: from .json import JSON jj = JSON(client=self, encoder=encoder, decoder=decoder) return jj + + def ft(self, index_name="idx"): + """Access the search namespace, providing support for redis search.""" + if 'search' not in self.loaded_modules: + raise ModuleError("search is not a loaded in the redis instance.") + + from .search import Search + s = Search(client=self, index_name=index_name) + return s diff --git a/redis/commands/search/__init__.py b/redis/commands/search/__init__.py new file mode 100644 index 0000000..8320ad4 --- /dev/null +++ b/redis/commands/search/__init__.py @@ -0,0 +1,96 @@ +from .commands import SearchCommands + + +class Search(SearchCommands): + """ + Create a client for talking to search. + It abstracts the API of the module and lets you just use the engine. + """ + + class BatchIndexer(object): + """ + A batch indexer allows you to automatically batch + document indexing in pipelines, flushing it every N documents. + """ + + def __init__(self, client, chunk_size=1000): + + self.client = client + self.execute_command = client.execute_command + self.pipeline = client.pipeline(transaction=False, shard_hint=None) + self.total = 0 + self.chunk_size = chunk_size + self.current_chunk = 0 + + def __del__(self): + if self.current_chunk: + self.commit() + + def add_document( + self, + doc_id, + nosave=False, + score=1.0, + payload=None, + replace=False, + partial=False, + no_create=False, + **fields + ): + """ + Add a document to the batch query + """ + self.client._add_document( + doc_id, + conn=self.pipeline, + nosave=nosave, + score=score, + payload=payload, + replace=replace, + partial=partial, + no_create=no_create, + **fields + ) + self.current_chunk += 1 + self.total += 1 + if self.current_chunk >= self.chunk_size: + self.commit() + + def add_document_hash( + self, + doc_id, + score=1.0, + replace=False, + ): + """ + Add a hash to the batch query + """ + self.client._add_document_hash( + doc_id, + conn=self.pipeline, + score=score, + replace=replace, + ) + self.current_chunk += 1 + self.total += 1 + if self.current_chunk >= self.chunk_size: + self.commit() + + def commit(self): + """ + Manually commit and flush the batch indexing query + """ + self.pipeline.execute() + self.current_chunk = 0 + + def __init__(self, client, index_name="idx"): + """ + Create a new Client for the given index_name. + The default name is `idx` + + If conn is not None, we employ an already existing redis connection + """ + self.client = client + self.index_name = index_name + self.execute_command = client.execute_command + self.pipeline = client.pipeline diff --git a/redis/commands/search/_util.py b/redis/commands/search/_util.py new file mode 100644 index 0000000..b4ac19f --- /dev/null +++ b/redis/commands/search/_util.py @@ -0,0 +1,10 @@ +import six + + +def to_string(s): + if isinstance(s, six.string_types): + return s + elif isinstance(s, six.binary_type): + return s.decode("utf-8", "ignore") + else: + return s # Not a string we care about diff --git a/redis/commands/search/aggregation.py b/redis/commands/search/aggregation.py new file mode 100644 index 0000000..df912f8 --- /dev/null +++ b/redis/commands/search/aggregation.py @@ -0,0 +1,408 @@ +from six import string_types + +FIELDNAME = object() + + +class Limit(object): + def __init__(self, offset=0, count=0): + self.offset = offset + self.count = count + + def build_args(self): + if self.count: + return ["LIMIT", str(self.offset), str(self.count)] + else: + return [] + + +class Reducer(object): + """ + Base reducer object for all reducers. + + See the `redisearch.reducers` module for the actual reducers. + """ + + NAME = None + + def __init__(self, *args): + self._args = args + self._field = None + self._alias = None + + def alias(self, alias): + """ + Set the alias for this reducer. + + ### Parameters + + - **alias**: The value of the alias for this reducer. If this is the + special value `aggregation.FIELDNAME` then this reducer will be + aliased using the same name as the field upon which it operates. + Note that using `FIELDNAME` is only possible on reducers which + operate on a single field value. + + This method returns the `Reducer` object making it suitable for + chaining. + """ + if alias is FIELDNAME: + if not self._field: + raise ValueError("Cannot use FIELDNAME alias with no field") + # Chop off initial '@' + alias = self._field[1:] + self._alias = alias + return self + + @property + def args(self): + return self._args + + +class SortDirection(object): + """ + This special class is used to indicate sort direction. + """ + + DIRSTRING = None + + def __init__(self, field): + self.field = field + + +class Asc(SortDirection): + """ + Indicate that the given field should be sorted in ascending order + """ + + DIRSTRING = "ASC" + + +class Desc(SortDirection): + """ + Indicate that the given field should be sorted in descending order + """ + + DIRSTRING = "DESC" + + +class Group(object): + """ + This object automatically created in the `AggregateRequest.group_by()` + """ + + def __init__(self, fields, reducers): + if not reducers: + raise ValueError("Need at least one reducer") + + fields = [fields] if isinstance(fields, string_types) else fields + reducers = [reducers] if isinstance(reducers, Reducer) else reducers + + self.fields = fields + self.reducers = reducers + self.limit = Limit() + + def build_args(self): + ret = ["GROUPBY", str(len(self.fields))] + ret.extend(self.fields) + for reducer in self.reducers: + ret += ["REDUCE", reducer.NAME, str(len(reducer.args))] + ret.extend(reducer.args) + if reducer._alias is not None: + ret += ["AS", reducer._alias] + return ret + + +class Projection(object): + """ + This object automatically created in the `AggregateRequest.apply()` + """ + + def __init__(self, projector, alias=None): + self.alias = alias + self.projector = projector + + def build_args(self): + ret = ["APPLY", self.projector] + if self.alias is not None: + ret += ["AS", self.alias] + + return ret + + +class SortBy(object): + """ + This object automatically created in the `AggregateRequest.sort_by()` + """ + + def __init__(self, fields, max=0): + self.fields = fields + self.max = max + + def build_args(self): + fields_args = [] + for f in self.fields: + if isinstance(f, SortDirection): + fields_args += [f.field, f.DIRSTRING] + else: + fields_args += [f] + + ret = ["SORTBY", str(len(fields_args))] + ret.extend(fields_args) + if self.max > 0: + ret += ["MAX", str(self.max)] + + return ret + + +class AggregateRequest(object): + """ + Aggregation request which can be passed to `Client.aggregate`. + """ + + def __init__(self, query="*"): + """ + Create an aggregation request. This request may then be passed to + `client.aggregate()`. + + In order for the request to be usable, it must contain at least one + group. + + - **query** Query string for filtering records. + + All member methods (except `build_args()`) + return the object itself, making them useful for chaining. + """ + self._query = query + self._aggregateplan = [] + self._loadfields = [] + self._limit = Limit() + self._max = 0 + self._with_schema = False + self._verbatim = False + self._cursor = [] + + def load(self, *fields): + """ + Indicate the fields to be returned in the response. These fields are + returned in addition to any others implicitly specified. + + ### Parameters + + - **fields**: One or more fields in the format of `@field` + """ + self._loadfields.extend(fields) + return self + + def group_by(self, fields, *reducers): + """ + Specify by which fields to group the aggregation. + + ### Parameters + + - **fields**: Fields to group by. This can either be a single string, + or a list of strings. both cases, the field should be specified as + `@field`. + - **reducers**: One or more reducers. Reducers may be found in the + `aggregation` module. + """ + group = Group(fields, reducers) + self._aggregateplan.extend(group.build_args()) + + return self + + def apply(self, **kwexpr): + """ + Specify one or more projection expressions to add to each result + + ### Parameters + + - **kwexpr**: One or more key-value pairs for a projection. The key is + the alias for the projection, and the value is the projection + expression itself, for example `apply(square_root="sqrt(@foo)")` + """ + for alias, expr in kwexpr.items(): + projection = Projection(expr, alias) + self._aggregateplan.extend(projection.build_args()) + + return self + + def limit(self, offset, num): + """ + Sets the limit for the most recent group or query. + + If no group has been defined yet (via `group_by()`) then this sets + the limit for the initial pool of results from the query. Otherwise, + this limits the number of items operated on from the previous group. + + Setting a limit on the initial search results may be useful when + attempting to execute an aggregation on a sample of a large data set. + + ### Parameters + + - **offset**: Result offset from which to begin paging + - **num**: Number of results to return + + + Example of sorting the initial results: + + ``` + AggregateRequest("@sale_amount:[10000, inf]")\ + .limit(0, 10)\ + .group_by("@state", r.count()) + ``` + + Will only group by the states found in the first 10 results of the + query `@sale_amount:[10000, inf]`. On the other hand, + + ``` + AggregateRequest("@sale_amount:[10000, inf]")\ + .limit(0, 1000)\ + .group_by("@state", r.count()\ + .limit(0, 10) + ``` + + Will group all the results matching the query, but only return the + first 10 groups. + + If you only wish to return a *top-N* style query, consider using + `sort_by()` instead. + + """ + limit = Limit(offset, num) + self._limit = limit + return self + + def sort_by(self, *fields, **kwargs): + """ + Indicate how the results should be sorted. This can also be used for + *top-N* style queries + + ### Parameters + + - **fields**: The fields by which to sort. This can be either a single + field or a list of fields. If you wish to specify order, you can + use the `Asc` or `Desc` wrapper classes. + - **max**: Maximum number of results to return. This can be + used instead of `LIMIT` and is also faster. + + + Example of sorting by `foo` ascending and `bar` descending: + + ``` + sort_by(Asc("@foo"), Desc("@bar")) + ``` + + Return the top 10 customers: + + ``` + AggregateRequest()\ + .group_by("@customer", r.sum("@paid").alias(FIELDNAME))\ + .sort_by(Desc("@paid"), max=10) + ``` + """ + if isinstance(fields, (string_types, SortDirection)): + fields = [fields] + + max = kwargs.get("max", 0) + sortby = SortBy(fields, max) + + self._aggregateplan.extend(sortby.build_args()) + return self + + def filter(self, expressions): + """ + Specify filter for post-query results using predicates relating to + values in the result set. + + ### Parameters + + - **fields**: Fields to group by. This can either be a single string, + or a list of strings. + """ + if isinstance(expressions, string_types): + expressions = [expressions] + + for expression in expressions: + self._aggregateplan.extend(["FILTER", expression]) + + return self + + def with_schema(self): + """ + If set, the `schema` property will contain a list of `[field, type]` + entries in the result object. + """ + self._with_schema = True + return self + + def verbatim(self): + self._verbatim = True + return self + + def cursor(self, count=0, max_idle=0.0): + args = ["WITHCURSOR"] + if count: + args += ["COUNT", str(count)] + if max_idle: + args += ["MAXIDLE", str(max_idle * 1000)] + self._cursor = args + return self + + def _limit_2_args(self, limit): + if limit[1]: + return ["LIMIT"] + [str(x) for x in limit] + else: + return [] + + def build_args(self): + # @foo:bar ... + ret = [self._query] + + if self._with_schema: + ret.append("WITHSCHEMA") + + if self._verbatim: + ret.append("VERBATIM") + + if self._cursor: + ret += self._cursor + + if self._loadfields: + ret.append("LOAD") + ret.append(str(len(self._loadfields))) + ret.extend(self._loadfields) + + ret.extend(self._aggregateplan) + + ret += self._limit.build_args() + + return ret + + +class Cursor(object): + def __init__(self, cid): + self.cid = cid + self.max_idle = 0 + self.count = 0 + + def build_args(self): + args = [str(self.cid)] + if self.max_idle: + args += ["MAXIDLE", str(self.max_idle)] + if self.count: + args += ["COUNT", str(self.count)] + return args + + +class AggregateResult(object): + def __init__(self, rows, cursor, schema): + self.rows = rows + self.cursor = cursor + self.schema = schema + + def __repr__(self): + return "<{} at 0x{:x} Rows={}, Cursor={}>".format( + self.__class__.__name__, + id(self), + len(self.rows), + self.cursor.cid if self.cursor else -1, + ) diff --git a/redis/commands/search/commands.py b/redis/commands/search/commands.py new file mode 100644 index 0000000..6074d29 --- /dev/null +++ b/redis/commands/search/commands.py @@ -0,0 +1,704 @@ +import itertools +import time +import six + +from .document import Document +from .result import Result +from .query import Query +from ._util import to_string +from .aggregation import AggregateRequest, AggregateResult, Cursor +from .suggestion import SuggestionParser + +NUMERIC = "NUMERIC" + +CREATE_CMD = "FT.CREATE" +ALTER_CMD = "FT.ALTER" +SEARCH_CMD = "FT.SEARCH" +ADD_CMD = "FT.ADD" +ADDHASH_CMD = "FT.ADDHASH" +DROP_CMD = "FT.DROP" +EXPLAIN_CMD = "FT.EXPLAIN" +DEL_CMD = "FT.DEL" +AGGREGATE_CMD = "FT.AGGREGATE" +CURSOR_CMD = "FT.CURSOR" +SPELLCHECK_CMD = "FT.SPELLCHECK" +DICT_ADD_CMD = "FT.DICTADD" +DICT_DEL_CMD = "FT.DICTDEL" +DICT_DUMP_CMD = "FT.DICTDUMP" +GET_CMD = "FT.GET" +MGET_CMD = "FT.MGET" +CONFIG_CMD = "FT.CONFIG" +TAGVALS_CMD = "FT.TAGVALS" +ALIAS_ADD_CMD = "FT.ALIASADD" +ALIAS_UPDATE_CMD = "FT.ALIASUPDATE" +ALIAS_DEL_CMD = "FT.ALIASDEL" +INFO_CMD = "FT.INFO" +SUGADD_COMMAND = "FT.SUGADD" +SUGDEL_COMMAND = "FT.SUGDEL" +SUGLEN_COMMAND = "FT.SUGLEN" +SUGGET_COMMAND = "FT.SUGGET" +SYNUPDATE_CMD = "FT.SYNUPDATE" +SYNDUMP_CMD = "FT.SYNDUMP" + +NOOFFSETS = "NOOFFSETS" +NOFIELDS = "NOFIELDS" +STOPWORDS = "STOPWORDS" +WITHSCORES = "WITHSCORES" +FUZZY = "FUZZY" +WITHPAYLOADS = "WITHPAYLOADS" + + +class SearchCommands: + """Search commands.""" + + def batch_indexer(self, chunk_size=100): + """ + Create a new batch indexer from the client with a given chunk size + """ + return self.BatchIndexer(self, chunk_size=chunk_size) + + def create_index( + self, + fields, + no_term_offsets=False, + no_field_flags=False, + stopwords=None, + definition=None, + ): + """ + Create the search index. The index must not already exist. + + ### Parameters: + + - **fields**: a list of TextField or NumericField objects + - **no_term_offsets**: If true, we will not save term offsets in + the index + - **no_field_flags**: If true, we will not save field flags that + allow searching in specific fields + - **stopwords**: If not None, we create the index with this custom + stopword list. The list can be empty + """ + + args = [CREATE_CMD, self.index_name] + if definition is not None: + args += definition.args + if no_term_offsets: + args.append(NOOFFSETS) + if no_field_flags: + args.append(NOFIELDS) + if stopwords is not None and isinstance(stopwords, (list, tuple, set)): + args += [STOPWORDS, len(stopwords)] + if len(stopwords) > 0: + args += list(stopwords) + + args.append("SCHEMA") + try: + args += list(itertools.chain(*(f.redis_args() for f in fields))) + except TypeError: + args += fields.redis_args() + + return self.execute_command(*args) + + def alter_schema_add(self, fields): + """ + Alter the existing search index by adding new fields. The index + must already exist. + + ### Parameters: + + - **fields**: a list of Field objects to add for the index + """ + + args = [ALTER_CMD, self.index_name, "SCHEMA", "ADD"] + try: + args += list(itertools.chain(*(f.redis_args() for f in fields))) + except TypeError: + args += fields.redis_args() + + return self.execute_command(*args) + + def drop_index(self, delete_documents=True): + """ + Drop the index if it exists. Deprecated from RediSearch 2.0. + + ### Parameters: + + - **delete_documents**: If `True`, all documents will be deleted. + """ + keep_str = "" if delete_documents else "KEEPDOCS" + return self.execute_command(DROP_CMD, self.index_name, keep_str) + + def dropindex(self, delete_documents=False): + """ + Drop the index if it exists. + Replaced `drop_index` in RediSearch 2.0. + Default behavior was changed to not delete the indexed documents. + + ### Parameters: + + - **delete_documents**: If `True`, all documents will be deleted. + """ + keep_str = "" if delete_documents else "KEEPDOCS" + return self.execute_command(DROP_CMD, self.index_name, keep_str) + + def _add_document( + self, + doc_id, + conn=None, + nosave=False, + score=1.0, + payload=None, + replace=False, + partial=False, + language=None, + no_create=False, + **fields + ): + """ + Internal add_document used for both batch and single doc indexing + """ + if conn is None: + conn = self.client + + if partial or no_create: + replace = True + + args = [ADD_CMD, self.index_name, doc_id, score] + if nosave: + args.append("NOSAVE") + if payload is not None: + args.append("PAYLOAD") + args.append(payload) + if replace: + args.append("REPLACE") + if partial: + args.append("PARTIAL") + if no_create: + args.append("NOCREATE") + if language: + args += ["LANGUAGE", language] + args.append("FIELDS") + args += list(itertools.chain(*fields.items())) + return conn.execute_command(*args) + + def _add_document_hash( + self, + doc_id, + conn=None, + score=1.0, + language=None, + replace=False, + ): + """ + Internal add_document_hash used for both batch and single doc indexing + """ + if conn is None: + conn = self.client + + args = [ADDHASH_CMD, self.index_name, doc_id, score] + + if replace: + args.append("REPLACE") + + if language: + args += ["LANGUAGE", language] + + return conn.execute_command(*args) + + def add_document( + self, + doc_id, + nosave=False, + score=1.0, + payload=None, + replace=False, + partial=False, + language=None, + no_create=False, + **fields + ): + """ + Add a single document to the index. + + ### Parameters + + - **doc_id**: the id of the saved document. + - **nosave**: if set to true, we just index the document, and don't + save a copy of it. This means that searches will just + return ids. + - **score**: the document ranking, between 0.0 and 1.0 + - **payload**: optional inner-index payload we can save for fast + i access in scoring functions + - **replace**: if True, and the document already is in the index, + we perform an update and reindex the document + - **partial**: if True, the fields specified will be added to the + existing document. + This has the added benefit that any fields specified + with `no_index` + will not be reindexed again. Implies `replace` + - **language**: Specify the language used for document tokenization. + - **no_create**: if True, the document is only updated and reindexed + if it already exists. + If the document does not exist, an error will be + returned. Implies `replace` + - **fields** kwargs dictionary of the document fields to be saved + and/or indexed. + NOTE: Geo points shoule be encoded as strings of "lon,lat" + """ + return self._add_document( + doc_id, + conn=None, + nosave=nosave, + score=score, + payload=payload, + replace=replace, + partial=partial, + language=language, + no_create=no_create, + **fields + ) + + def add_document_hash( + self, + doc_id, + score=1.0, + language=None, + replace=False, + ): + """ + Add a hash document to the index. + + ### Parameters + + - **doc_id**: the document's id. This has to be an existing HASH key + in Redis that will hold the fields the index needs. + - **score**: the document ranking, between 0.0 and 1.0 + - **replace**: if True, and the document already is in the index, we + perform an update and reindex the document + - **language**: Specify the language used for document tokenization. + """ + return self._add_document_hash( + doc_id, + conn=None, + score=score, + language=language, + replace=replace, + ) + + def delete_document(self, doc_id, conn=None, delete_actual_document=False): + """ + Delete a document from index + Returns 1 if the document was deleted, 0 if not + + ### Parameters + + - **delete_actual_document**: if set to True, RediSearch also delete + the actual document if it is in the index + """ + args = [DEL_CMD, self.index_name, doc_id] + if conn is None: + conn = self.client + if delete_actual_document: + args.append("DD") + + return conn.execute_command(*args) + + def load_document(self, id): + """ + Load a single document by id + """ + fields = self.client.hgetall(id) + if six.PY3: + f2 = {to_string(k): to_string(v) for k, v in fields.items()} + fields = f2 + + try: + del fields["id"] + except KeyError: + pass + + return Document(id=id, **fields) + + def get(self, *ids): + """ + Returns the full contents of multiple documents. + + ### Parameters + + - **ids**: the ids of the saved documents. + """ + + return self.client.execute_command(MGET_CMD, self.index_name, *ids) + + def info(self): + """ + Get info an stats about the the current index, including the number of + documents, memory consumption, etc + """ + + res = self.client.execute_command(INFO_CMD, self.index_name) + it = six.moves.map(to_string, res) + return dict(six.moves.zip(it, it)) + + def _mk_query_args(self, query): + args = [self.index_name] + + if isinstance(query, six.string_types): + # convert the query from a text to a query object + query = Query(query) + if not isinstance(query, Query): + raise ValueError("Bad query type %s" % type(query)) + + args += query.get_args() + return args, query + + def search(self, query): + """ + Search the index for a given query, and return a result of documents + + ### Parameters + + - **query**: the search query. Either a text for simple queries with + default parameters, or a Query object for complex queries. + See RediSearch's documentation on query format + """ + args, query = self._mk_query_args(query) + st = time.time() + res = self.execute_command(SEARCH_CMD, *args) + + return Result( + res, + not query._no_content, + duration=(time.time() - st) * 1000.0, + has_payload=query._with_payloads, + with_scores=query._with_scores, + ) + + def explain(self, query): + args, query_text = self._mk_query_args(query) + return self.execute_command(EXPLAIN_CMD, *args) + + def aggregate(self, query): + """ + Issue an aggregation query + + ### Parameters + + **query**: This can be either an `AggeregateRequest`, or a `Cursor` + + An `AggregateResult` object is returned. You can access the rows from + its `rows` property, which will always yield the rows of the result. + """ + if isinstance(query, AggregateRequest): + has_cursor = bool(query._cursor) + cmd = [AGGREGATE_CMD, self.index_name] + query.build_args() + elif isinstance(query, Cursor): + has_cursor = True + cmd = [CURSOR_CMD, "READ", self.index_name] + query.build_args() + else: + raise ValueError("Bad query", query) + + raw = self.execute_command(*cmd) + if has_cursor: + if isinstance(query, Cursor): + query.cid = raw[1] + cursor = query + else: + cursor = Cursor(raw[1]) + raw = raw[0] + else: + cursor = None + + if isinstance(query, AggregateRequest) and query._with_schema: + schema = raw[0] + rows = raw[2:] + else: + schema = None + rows = raw[1:] + + res = AggregateResult(rows, cursor, schema) + return res + + def spellcheck(self, query, distance=None, include=None, exclude=None): + """ + Issue a spellcheck query + + ### Parameters + + **query**: search query. + **distance***: the maximal Levenshtein distance for spelling + suggestions (default: 1, max: 4). + **include**: specifies an inclusion custom dictionary. + **exclude**: specifies an exclusion custom dictionary. + """ + cmd = [SPELLCHECK_CMD, self.index_name, query] + if distance: + cmd.extend(["DISTANCE", distance]) + + if include: + cmd.extend(["TERMS", "INCLUDE", include]) + + if exclude: + cmd.extend(["TERMS", "EXCLUDE", exclude]) + + raw = self.execute_command(*cmd) + + corrections = {} + if raw == 0: + return corrections + + for _correction in raw: + if isinstance(_correction, six.integer_types) and _correction == 0: + continue + + if len(_correction) != 3: + continue + if not _correction[2]: + continue + if not _correction[2][0]: + continue + + # For spellcheck output + # 1) 1) "TERM" + # 2) "{term1}" + # 3) 1) 1) "{score1}" + # 2) "{suggestion1}" + # 2) 1) "{score2}" + # 2) "{suggestion2}" + # + # Following dictionary will be made + # corrections = { + # '{term1}': [ + # {'score': '{score1}', 'suggestion': '{suggestion1}'}, + # {'score': '{score2}', 'suggestion': '{suggestion2}'} + # ] + # } + corrections[_correction[1]] = [ + {"score": _item[0], "suggestion": _item[1]} + for _item in _correction[2] + ] + + return corrections + + def dict_add(self, name, *terms): + """Adds terms to a dictionary. + + ### Parameters + + - **name**: Dictionary name. + - **terms**: List of items for adding to the dictionary. + """ + cmd = [DICT_ADD_CMD, name] + cmd.extend(terms) + return self.execute_command(*cmd) + + def dict_del(self, name, *terms): + """Deletes terms from a dictionary. + + ### Parameters + + - **name**: Dictionary name. + - **terms**: List of items for removing from the dictionary. + """ + cmd = [DICT_DEL_CMD, name] + cmd.extend(terms) + return self.execute_command(*cmd) + + def dict_dump(self, name): + """Dumps all terms in the given dictionary. + + ### Parameters + + - **name**: Dictionary name. + """ + cmd = [DICT_DUMP_CMD, name] + return self.execute_command(*cmd) + + def config_set(self, option, value): + """Set runtime configuration option. + + ### Parameters + + - **option**: the name of the configuration option. + - **value**: a value for the configuration option. + """ + cmd = [CONFIG_CMD, "SET", option, value] + raw = self.execute_command(*cmd) + return raw == "OK" + + def config_get(self, option): + """Get runtime configuration option value. + + ### Parameters + + - **option**: the name of the configuration option. + """ + cmd = [CONFIG_CMD, "GET", option] + res = {} + raw = self.execute_command(*cmd) + if raw: + for kvs in raw: + res[kvs[0]] = kvs[1] + return res + + def tagvals(self, tagfield): + """ + Return a list of all possible tag values + + ### Parameters + + - **tagfield**: Tag field name + """ + + return self.execute_command(TAGVALS_CMD, self.index_name, tagfield) + + def aliasadd(self, alias): + """ + Alias a search index - will fail if alias already exists + + ### Parameters + + - **alias**: Name of the alias to create + """ + + return self.execute_command(ALIAS_ADD_CMD, alias, self.index_name) + + def aliasupdate(self, alias): + """ + Updates an alias - will fail if alias does not already exist + + ### Parameters + + - **alias**: Name of the alias to create + """ + + return self.execute_command(ALIAS_UPDATE_CMD, alias, self.index_name) + + def aliasdel(self, alias): + """ + Removes an alias to a search index + + ### Parameters + + - **alias**: Name of the alias to delete + """ + return self.execute_command(ALIAS_DEL_CMD, alias) + + def sugadd(self, key, *suggestions, **kwargs): + """ + Add suggestion terms to the AutoCompleter engine. Each suggestion has + a score and string. + If kwargs["increment"] is true and the terms are already in the + server's dictionary, we increment their scores. + More information `here <https://oss.redis.com/redisearch/master/Commands/#ftsugadd>`_. # noqa + """ + # If Transaction is not False it will MULTI/EXEC which will error + pipe = self.pipeline(transaction=False) + for sug in suggestions: + args = [SUGADD_COMMAND, key, sug.string, sug.score] + if kwargs.get("increment"): + args.append("INCR") + if sug.payload: + args.append("PAYLOAD") + args.append(sug.payload) + + pipe.execute_command(*args) + + return pipe.execute()[-1] + + def suglen(self, key): + """ + Return the number of entries in the AutoCompleter index. + More information `here <https://oss.redis.com/redisearch/master/Commands/#ftsuglen>`_. # noqa + """ + return self.execute_command(SUGLEN_COMMAND, key) + + def sugdel(self, key, string): + """ + Delete a string from the AutoCompleter index. + Returns 1 if the string was found and deleted, 0 otherwise. + More information `here <https://oss.redis.com/redisearch/master/Commands/#ftsugdel>`_. # noqa + """ + return self.execute_command(SUGDEL_COMMAND, key, string) + + def sugget( + self, key, prefix, fuzzy=False, num=10, with_scores=False, + with_payloads=False + ): + """ + Get a list of suggestions from the AutoCompleter, for a given prefix. + More information `here <https://oss.redis.com/redisearch/master/Commands/#ftsugget>`_. # noqa + + Parameters: + + prefix : str + The prefix we are searching. **Must be valid ascii or utf-8** + fuzzy : bool + If set to true, the prefix search is done in fuzzy mode. + **NOTE**: Running fuzzy searches on short (<3 letters) prefixes + can be very + slow, and even scan the entire index. + with_scores : bool + If set to true, we also return the (refactored) score of + each suggestion. + This is normally not needed, and is NOT the original score + inserted into the index. + with_payloads : bool + Return suggestion payloads + num : int + The maximum number of results we return. Note that we might + return less. The algorithm trims irrelevant suggestions. + + Returns: + + list: + A list of Suggestion objects. If with_scores was False, the + score of all suggestions is 1. + """ + args = [SUGGET_COMMAND, key, prefix, "MAX", num] + if fuzzy: + args.append(FUZZY) + if with_scores: + args.append(WITHSCORES) + if with_payloads: + args.append(WITHPAYLOADS) + + ret = self.execute_command(*args) + results = [] + if not ret: + return results + + parser = SuggestionParser(with_scores, with_payloads, ret) + return [s for s in parser] + + def synupdate(self, groupid, skipinitial=False, *terms): + """ + Updates a synonym group. + The command is used to create or update a synonym group with + additional terms. + Only documents which were indexed after the update will be affected. + + Parameters: + + groupid : + Synonym group id. + skipinitial : bool + If set to true, we do not scan and index. + terms : + The terms. + """ + cmd = [SYNUPDATE_CMD, self.index_name, groupid] + if skipinitial: + cmd.extend(["SKIPINITIALSCAN"]) + cmd.extend(terms) + return self.execute_command(*cmd) + + def syndump(self): + """ + Dumps the contents of a synonym group. + + The command is used to dump the synonyms data structure. + Returns a list of synonym terms and their synonym group ids. + """ + raw = self.execute_command(SYNDUMP_CMD, self.index_name) + return {raw[i]: raw[i + 1] for i in range(0, len(raw), 2)} diff --git a/redis/commands/search/document.py b/redis/commands/search/document.py new file mode 100644 index 0000000..26ede34 --- /dev/null +++ b/redis/commands/search/document.py @@ -0,0 +1,16 @@ +import six + + +class Document(object): + """ + Represents a single document in a result set + """ + + def __init__(self, id, payload=None, **fields): + self.id = id + self.payload = payload + for k, v in six.iteritems(fields): + setattr(self, k, v) + + def __repr__(self): + return "Document %s" % self.__dict__ diff --git a/redis/commands/search/field.py b/redis/commands/search/field.py new file mode 100644 index 0000000..45114a4 --- /dev/null +++ b/redis/commands/search/field.py @@ -0,0 +1,94 @@ +class Field(object): + + NUMERIC = "NUMERIC" + TEXT = "TEXT" + WEIGHT = "WEIGHT" + GEO = "GEO" + TAG = "TAG" + SORTABLE = "SORTABLE" + NOINDEX = "NOINDEX" + AS = "AS" + + def __init__(self, name, args=[], sortable=False, + no_index=False, as_name=None): + self.name = name + self.args = args + self.args_suffix = list() + self.as_name = as_name + + if sortable: + self.args_suffix.append(Field.SORTABLE) + if no_index: + self.args_suffix.append(Field.NOINDEX) + + if no_index and not sortable: + raise ValueError("Non-Sortable non-Indexable fields are ignored") + + def append_arg(self, value): + self.args.append(value) + + def redis_args(self): + args = [self.name] + if self.as_name: + args += [self.AS, self.as_name] + args += self.args + args += self.args_suffix + return args + + +class TextField(Field): + """ + TextField is used to define a text field in a schema definition + """ + + NOSTEM = "NOSTEM" + PHONETIC = "PHONETIC" + + def __init__( + self, name, weight=1.0, no_stem=False, phonetic_matcher=None, **kwargs + ): + Field.__init__(self, name, + args=[Field.TEXT, Field.WEIGHT, weight], **kwargs) + + if no_stem: + Field.append_arg(self, self.NOSTEM) + if phonetic_matcher and phonetic_matcher in [ + "dm:en", + "dm:fr", + "dm:pt", + "dm:es", + ]: + Field.append_arg(self, self.PHONETIC) + Field.append_arg(self, phonetic_matcher) + + +class NumericField(Field): + """ + NumericField is used to define a numeric field in a schema definition + """ + + def __init__(self, name, **kwargs): + Field.__init__(self, name, args=[Field.NUMERIC], **kwargs) + + +class GeoField(Field): + """ + GeoField is used to define a geo-indexing field in a schema definition + """ + + def __init__(self, name, **kwargs): + Field.__init__(self, name, args=[Field.GEO], **kwargs) + + +class TagField(Field): + """ + TagField is a tag-indexing field with simpler compression and tokenization. + See http://redisearch.io/Tags/ + """ + + SEPARATOR = "SEPARATOR" + + def __init__(self, name, separator=",", **kwargs): + Field.__init__( + self, name, args=[Field.TAG, self.SEPARATOR, separator], **kwargs + ) diff --git a/redis/commands/search/indexDefinition.py b/redis/commands/search/indexDefinition.py new file mode 100644 index 0000000..4fbc609 --- /dev/null +++ b/redis/commands/search/indexDefinition.py @@ -0,0 +1,80 @@ +from enum import Enum + + +class IndexType(Enum): + """Enum of the currently supported index types.""" + + HASH = 1 + JSON = 2 + + +class IndexDefinition(object): + """IndexDefinition is used to define a index definition for automatic + indexing on Hash or Json update.""" + + def __init__( + self, + prefix=[], + filter=None, + language_field=None, + language=None, + score_field=None, + score=1.0, + payload_field=None, + index_type=None, + ): + self.args = [] + self._appendIndexType(index_type) + self._appendPrefix(prefix) + self._appendFilter(filter) + self._appendLanguage(language_field, language) + self._appendScore(score_field, score) + self._appendPayload(payload_field) + + def _appendIndexType(self, index_type): + """Append `ON HASH` or `ON JSON` according to the enum.""" + if index_type is IndexType.HASH: + self.args.extend(["ON", "HASH"]) + elif index_type is IndexType.JSON: + self.args.extend(["ON", "JSON"]) + elif index_type is not None: + raise RuntimeError("index_type must be one of {}". + format(list(IndexType))) + + def _appendPrefix(self, prefix): + """Append PREFIX.""" + if len(prefix) > 0: + self.args.append("PREFIX") + self.args.append(len(prefix)) + for p in prefix: + self.args.append(p) + + def _appendFilter(self, filter): + """Append FILTER.""" + if filter is not None: + self.args.append("FILTER") + self.args.append(filter) + + def _appendLanguage(self, language_field, language): + """Append LANGUAGE_FIELD and LANGUAGE.""" + if language_field is not None: + self.args.append("LANGUAGE_FIELD") + self.args.append(language_field) + if language is not None: + self.args.append("LANGUAGE") + self.args.append(language) + + def _appendScore(self, score_field, score): + """Append SCORE_FIELD and SCORE.""" + if score_field is not None: + self.args.append("SCORE_FIELD") + self.args.append(score_field) + if score is not None: + self.args.append("SCORE") + self.args.append(score) + + def _appendPayload(self, payload_field): + """Append PAYLOAD_FIELD.""" + if payload_field is not None: + self.args.append("PAYLOAD_FIELD") + self.args.append(payload_field) diff --git a/redis/commands/search/query.py b/redis/commands/search/query.py new file mode 100644 index 0000000..e2db7a4 --- /dev/null +++ b/redis/commands/search/query.py @@ -0,0 +1,328 @@ +import six + + +class Query(object): + """ + Query is used to build complex queries that have more parameters than just + the query string. The query string is set in the constructor, and other + options have setter functions. + + The setter functions return the query object, so they can be chained, + i.e. `Query("foo").verbatim().filter(...)` etc. + """ + + def __init__(self, query_string): + """ + Create a new query object. + The query string is set in the constructor, and other options have + setter functions. + """ + + self._query_string = query_string + self._offset = 0 + self._num = 10 + self._no_content = False + self._no_stopwords = False + self._fields = None + self._verbatim = False + self._with_payloads = False + self._with_scores = False + self._scorer = False + self._filters = list() + self._ids = None + self._slop = -1 + self._in_order = False + self._sortby = None + self._return_fields = [] + self._summarize_fields = [] + self._highlight_fields = [] + self._language = None + self._expander = None + + def query_string(self): + """Return the query string of this query only.""" + return self._query_string + + def limit_ids(self, *ids): + """Limit the results to a specific set of pre-known document + ids of any length.""" + self._ids = ids + return self + + def return_fields(self, *fields): + """Add fields to return fields.""" + self._return_fields += fields + return self + + def return_field(self, field, as_field=None): + """Add field to return fields (Optional: add 'AS' name + to the field).""" + self._return_fields.append(field) + if as_field is not None: + self._return_fields += ("AS", as_field) + return self + + def _mk_field_list(self, fields): + if not fields: + return [] + return \ + [fields] if isinstance(fields, six.string_types) else list(fields) + + def summarize(self, fields=None, context_len=None, + num_frags=None, sep=None): + """ + Return an abridged format of the field, containing only the segments of + the field which contain the matching term(s). + + If `fields` is specified, then only the mentioned fields are + summarized; otherwise all results are summarized. + + Server side defaults are used for each option (except `fields`) + if not specified + + - **fields** List of fields to summarize. All fields are summarized + if not specified + - **context_len** Amount of context to include with each fragment + - **num_frags** Number of fragments per document + - **sep** Separator string to separate fragments + """ + args = ["SUMMARIZE"] + fields = self._mk_field_list(fields) + if fields: + args += ["FIELDS", str(len(fields))] + fields + + if context_len is not None: + args += ["LEN", str(context_len)] + if num_frags is not None: + args += ["FRAGS", str(num_frags)] + if sep is not None: + args += ["SEPARATOR", sep] + + self._summarize_fields = args + return self + + def highlight(self, fields=None, tags=None): + """ + Apply specified markup to matched term(s) within the returned field(s). + + - **fields** If specified then only those mentioned fields are + highlighted, otherwise all fields are highlighted + - **tags** A list of two strings to surround the match. + """ + args = ["HIGHLIGHT"] + fields = self._mk_field_list(fields) + if fields: + args += ["FIELDS", str(len(fields))] + fields + if tags: + args += ["TAGS"] + list(tags) + + self._highlight_fields = args + return self + + def language(self, language): + """ + Analyze the query as being in the specified language. + + :param language: The language (e.g. `chinese` or `english`) + """ + self._language = language + return self + + def slop(self, slop): + """Allow a maximum of N intervening non matched terms between + phrase terms (0 means exact phrase). + """ + self._slop = slop + return self + + def in_order(self): + """ + Match only documents where the query terms appear in + the same order in the document. + i.e. for the query "hello world", we do not match "world hello" + """ + self._in_order = True + return self + + def scorer(self, scorer): + """ + Use a different scoring function to evaluate document relevance. + Default is `TFIDF`. + + :param scorer: The scoring function to use + (e.g. `TFIDF.DOCNORM` or `BM25`) + """ + self._scorer = scorer + return self + + def get_args(self): + """Format the redis arguments for this query and return them.""" + args = [self._query_string] + args += self._get_args_tags() + args += self._summarize_fields + self._highlight_fields + args += ["LIMIT", self._offset, self._num] + return args + + def _get_args_tags(self): + args = [] + if self._no_content: + args.append("NOCONTENT") + if self._fields: + args.append("INFIELDS") + args.append(len(self._fields)) + args += self._fields + if self._verbatim: + args.append("VERBATIM") + if self._no_stopwords: + args.append("NOSTOPWORDS") + if self._filters: + for flt in self._filters: + if not isinstance(flt, Filter): + raise AttributeError("Did not receive a Filter object.") + args += flt.args + if self._with_payloads: + args.append("WITHPAYLOADS") + if self._scorer: + args += ["SCORER", self._scorer] + if self._with_scores: + args.append("WITHSCORES") + if self._ids: + args.append("INKEYS") + args.append(len(self._ids)) + args += self._ids + if self._slop >= 0: + args += ["SLOP", self._slop] + if self._in_order: + args.append("INORDER") + if self._return_fields: + args.append("RETURN") + args.append(len(self._return_fields)) + args += self._return_fields + if self._sortby: + if not isinstance(self._sortby, SortbyField): + raise AttributeError("Did not receive a SortByField.") + args.append("SORTBY") + args += self._sortby.args + if self._language: + args += ["LANGUAGE", self._language] + if self._expander: + args += ["EXPANDER", self._expander] + + return args + + def paging(self, offset, num): + """ + Set the paging for the query (defaults to 0..10). + + - **offset**: Paging offset for the results. Defaults to 0 + - **num**: How many results do we want + """ + self._offset = offset + self._num = num + return self + + def verbatim(self): + """Set the query to be verbatim, i.e. use no query expansion + or stemming. + """ + self._verbatim = True + return self + + def no_content(self): + """Set the query to only return ids and not the document content.""" + self._no_content = True + return self + + def no_stopwords(self): + """ + Prevent the query from being filtered for stopwords. + Only useful in very big queries that you are certain contain + no stopwords. + """ + self._no_stopwords = True + return self + + def with_payloads(self): + """Ask the engine to return document payloads.""" + self._with_payloads = True + return self + + def with_scores(self): + """Ask the engine to return document search scores.""" + self._with_scores = True + return self + + def limit_fields(self, *fields): + """ + Limit the search to specific TEXT fields only. + + - **fields**: A list of strings, case sensitive field names + from the defined schema. + """ + self._fields = fields + return self + + def add_filter(self, flt): + """ + Add a numeric or geo filter to the query. + **Currently only one of each filter is supported by the engine** + + - **flt**: A NumericFilter or GeoFilter object, used on a + corresponding field + """ + + self._filters.append(flt) + return self + + def sort_by(self, field, asc=True): + """ + Add a sortby field to the query. + + - **field** - the name of the field to sort by + - **asc** - when `True`, sorting will be done in asceding order + """ + self._sortby = SortbyField(field, asc) + return self + + def expander(self, expander): + """ + Add a expander field to the query. + + - **expander** - the name of the expander + """ + self._expander = expander + return self + + +class Filter(object): + def __init__(self, keyword, field, *args): + self.args = [keyword, field] + list(args) + + +class NumericFilter(Filter): + INF = "+inf" + NEG_INF = "-inf" + + def __init__(self, field, minval, maxval, minExclusive=False, + maxExclusive=False): + args = [ + minval if not minExclusive else "({}".format(minval), + maxval if not maxExclusive else "({}".format(maxval), + ] + + Filter.__init__(self, "FILTER", field, *args) + + +class GeoFilter(Filter): + METERS = "m" + KILOMETERS = "km" + FEET = "ft" + MILES = "mi" + + def __init__(self, field, lon, lat, radius, unit=KILOMETERS): + Filter.__init__(self, "GEOFILTER", field, lon, lat, radius, unit) + + +class SortbyField(object): + def __init__(self, field, asc=True): + self.args = [field, "ASC" if asc else "DESC"] diff --git a/redis/commands/search/querystring.py b/redis/commands/search/querystring.py new file mode 100644 index 0000000..f5f59b7 --- /dev/null +++ b/redis/commands/search/querystring.py @@ -0,0 +1,324 @@ +from six import string_types, integer_types + + +def tags(*t): + """ + Indicate that the values should be matched to a tag field + + ### Parameters + + - **t**: Tags to search for + """ + if not t: + raise ValueError("At least one tag must be specified") + return TagValue(*t) + + +def between(a, b, inclusive_min=True, inclusive_max=True): + """ + Indicate that value is a numeric range + """ + return RangeValue(a, b, inclusive_min=inclusive_min, + inclusive_max=inclusive_max) + + +def equal(n): + """ + Match a numeric value + """ + return between(n, n) + + +def lt(n): + """ + Match any value less than n + """ + return between(None, n, inclusive_max=False) + + +def le(n): + """ + Match any value less or equal to n + """ + return between(None, n, inclusive_max=True) + + +def gt(n): + """ + Match any value greater than n + """ + return between(n, None, inclusive_min=False) + + +def ge(n): + """ + Match any value greater or equal to n + """ + return between(n, None, inclusive_min=True) + + +def geo(lat, lon, radius, unit="km"): + """ + Indicate that value is a geo region + """ + return GeoValue(lat, lon, radius, unit) + + +class Value(object): + @property + def combinable(self): + """ + Whether this type of value may be combined with other values + for the same field. This makes the filter potentially more efficient + """ + return False + + @staticmethod + def make_value(v): + """ + Convert an object to a value, if it is not a value already + """ + if isinstance(v, Value): + return v + return ScalarValue(v) + + def to_string(self): + raise NotImplementedError() + + def __str__(self): + return self.to_string() + + +class RangeValue(Value): + combinable = False + + def __init__(self, a, b, inclusive_min=False, inclusive_max=False): + if a is None: + a = "-inf" + if b is None: + b = "inf" + self.range = [str(a), str(b)] + self.inclusive_min = inclusive_min + self.inclusive_max = inclusive_max + + def to_string(self): + return "[{1}{0[0]} {2}{0[1]}]".format( + self.range, + "(" if not self.inclusive_min else "", + "(" if not self.inclusive_max else "", + ) + + +class ScalarValue(Value): + combinable = True + + def __init__(self, v): + self.v = str(v) + + def to_string(self): + return self.v + + +class TagValue(Value): + combinable = False + + def __init__(self, *tags): + self.tags = tags + + def to_string(self): + return "{" + " | ".join(str(t) for t in self.tags) + "}" + + +class GeoValue(Value): + def __init__(self, lon, lat, radius, unit="km"): + self.lon = lon + self.lat = lat + self.radius = radius + self.unit = unit + + +class Node(object): + def __init__(self, *children, **kwparams): + """ + Create a node + + ### Parameters + + - **children**: One or more sub-conditions. These can be additional + `intersect`, `disjunct`, `union`, `optional`, or any other `Node` + type. + + The semantics of multiple conditions are dependent on the type of + query. For an `intersection` node, this amounts to a logical AND, + for a `union` node, this amounts to a logical `OR`. + + - **kwparams**: key-value parameters. Each key is the name of a field, + and the value should be a field value. This can be one of the + following: + + - Simple string (for text field matches) + - value returned by one of the helper functions + - list of either a string or a value + + + ### Examples + + Field `num` should be between 1 and 10 + ``` + intersect(num=between(1, 10) + ``` + + Name can either be `bob` or `john` + + ``` + union(name=("bob", "john")) + ``` + + Don't select countries in Israel, Japan, or US + + ``` + disjunct_union(country=("il", "jp", "us")) + ``` + """ + + self.params = [] + + kvparams = {} + for k, v in kwparams.items(): + curvals = kvparams.setdefault(k, []) + if isinstance(v, (string_types, integer_types, float)): + curvals.append(Value.make_value(v)) + elif isinstance(v, Value): + curvals.append(v) + else: + curvals.extend(Value.make_value(subv) for subv in v) + + self.params += [Node.to_node(p) for p in children] + + for k, v in kvparams.items(): + self.params.extend(self.join_fields(k, v)) + + def join_fields(self, key, vals): + if len(vals) == 1: + return [BaseNode("@{}:{}".format(key, vals[0].to_string()))] + if not vals[0].combinable: + return [BaseNode("@{}:{}".format(key, + v.to_string())) for v in vals] + s = BaseNode( + "@{}:({})".format(key, + self.JOINSTR.join(v.to_string() for v in vals)) + ) + return [s] + + @classmethod + def to_node(cls, obj): # noqa + if isinstance(obj, Node): + return obj + return BaseNode(obj) + + @property + def JOINSTR(self): + raise NotImplementedError() + + def to_string(self, with_parens=None): + with_parens = self._should_use_paren(with_parens) + pre, post = ("(", ")") if with_parens else ("", "") + return "{}{}{}".format( + pre, self.JOINSTR.join(n.to_string() for n in self.params), post + ) + + def _should_use_paren(self, optval): + if optval is not None: + return optval + return len(self.params) > 1 + + def __str__(self): + return self.to_string() + + +class BaseNode(Node): + def __init__(self, s): + super(BaseNode, self).__init__() + self.s = str(s) + + def to_string(self, with_parens=None): + return self.s + + +class IntersectNode(Node): + """ + Create an intersection node. All children need to be satisfied in order for + this node to evaluate as true + """ + + JOINSTR = " " + + +class UnionNode(Node): + """ + Create a union node. Any of the children need to be satisfied in order for + this node to evaluate as true + """ + + JOINSTR = "|" + + +class DisjunctNode(IntersectNode): + """ + Create a disjunct node. In order for this node to be true, all of its + children must evaluate to false + """ + + def to_string(self, with_parens=None): + with_parens = self._should_use_paren(with_parens) + ret = super(DisjunctNode, self).to_string(with_parens=False) + if with_parens: + return "(-" + ret + ")" + else: + return "-" + ret + + +class DistjunctUnion(DisjunctNode): + """ + This node is true if *all* of its children are false. This is equivalent to + ``` + disjunct(union(...)) + ``` + """ + + JOINSTR = "|" + + +class OptionalNode(IntersectNode): + """ + Create an optional node. If this nodes evaluates to true, then the document + will be rated higher in score/rank. + """ + + def to_string(self, with_parens=None): + with_parens = self._should_use_paren(with_parens) + ret = super(OptionalNode, self).to_string(with_parens=False) + if with_parens: + return "(~" + ret + ")" + else: + return "~" + ret + + +def intersect(*args, **kwargs): + return IntersectNode(*args, **kwargs) + + +def union(*args, **kwargs): + return UnionNode(*args, **kwargs) + + +def disjunct(*args, **kwargs): + return DisjunctNode(*args, **kwargs) + + +def disjunct_union(*args, **kwargs): + return DistjunctUnion(*args, **kwargs) + + +def querystring(*args, **kwargs): + return intersect(*args, **kwargs).to_string() diff --git a/redis/commands/search/reducers.py b/redis/commands/search/reducers.py new file mode 100644 index 0000000..6cbbf2f --- /dev/null +++ b/redis/commands/search/reducers.py @@ -0,0 +1,178 @@ +from .aggregation import Reducer, SortDirection + + +class FieldOnlyReducer(Reducer): + def __init__(self, field): + super(FieldOnlyReducer, self).__init__(field) + self._field = field + + +class count(Reducer): + """ + Counts the number of results in the group + """ + + NAME = "COUNT" + + def __init__(self): + super(count, self).__init__() + + +class sum(FieldOnlyReducer): + """ + Calculates the sum of all the values in the given fields within the group + """ + + NAME = "SUM" + + def __init__(self, field): + super(sum, self).__init__(field) + + +class min(FieldOnlyReducer): + """ + Calculates the smallest value in the given field within the group + """ + + NAME = "MIN" + + def __init__(self, field): + super(min, self).__init__(field) + + +class max(FieldOnlyReducer): + """ + Calculates the largest value in the given field within the group + """ + + NAME = "MAX" + + def __init__(self, field): + super(max, self).__init__(field) + + +class avg(FieldOnlyReducer): + """ + Calculates the mean value in the given field within the group + """ + + NAME = "AVG" + + def __init__(self, field): + super(avg, self).__init__(field) + + +class tolist(FieldOnlyReducer): + """ + Returns all the matched properties in a list + """ + + NAME = "TOLIST" + + def __init__(self, field): + super(tolist, self).__init__(field) + + +class count_distinct(FieldOnlyReducer): + """ + Calculate the number of distinct values contained in all the results in + the group for the given field + """ + + NAME = "COUNT_DISTINCT" + + def __init__(self, field): + super(count_distinct, self).__init__(field) + + +class count_distinctish(FieldOnlyReducer): + """ + Calculate the number of distinct values contained in all the results in the + group for the given field. This uses a faster algorithm than + `count_distinct` but is less accurate + """ + + NAME = "COUNT_DISTINCTISH" + + +class quantile(Reducer): + """ + Return the value for the nth percentile within the range of values for the + field within the group. + """ + + NAME = "QUANTILE" + + def __init__(self, field, pct): + super(quantile, self).__init__(field, str(pct)) + self._field = field + + +class stddev(FieldOnlyReducer): + """ + Return the standard deviation for the values within the group + """ + + NAME = "STDDEV" + + def __init__(self, field): + super(stddev, self).__init__(field) + + +class first_value(Reducer): + """ + Selects the first value within the group according to sorting parameters + """ + + NAME = "FIRST_VALUE" + + def __init__(self, field, *byfields): + """ + Selects the first value of the given field within the group. + + ### Parameter + + - **field**: Source field used for the value + - **byfields**: How to sort the results. This can be either the + *class* of `aggregation.Asc` or `aggregation.Desc` in which + case the field `field` is also used as the sort input. + + `byfields` can also be one or more *instances* of `Asc` or `Desc` + indicating the sort order for these fields + """ + + fieldstrs = [] + if ( + len(byfields) == 1 + and isinstance(byfields[0], type) + and issubclass(byfields[0], SortDirection) + ): + byfields = [byfields[0](field)] + + for f in byfields: + fieldstrs += [f.field, f.DIRSTRING] + + args = [field] + if fieldstrs: + args += ["BY"] + fieldstrs + super(first_value, self).__init__(*args) + self._field = field + + +class random_sample(Reducer): + """ + Returns a random sample of items from the dataset, from the given property + """ + + NAME = "RANDOM_SAMPLE" + + def __init__(self, field, size): + """ + ### Parameter + + **field**: Field to sample from + **size**: Return this many items (can be less) + """ + args = [field, str(size)] + super(random_sample, self).__init__(*args) + self._field = field diff --git a/redis/commands/search/result.py b/redis/commands/search/result.py new file mode 100644 index 0000000..afc83f8 --- /dev/null +++ b/redis/commands/search/result.py @@ -0,0 +1,75 @@ +from six.moves import xrange, zip as izip + +from .document import Document +from ._util import to_string + + +class Result(object): + """ + Represents the result of a search query, and has an array of Document + objects + """ + + def __init__( + self, res, hascontent, duration=0, has_payload=False, with_scores=False + ): + """ + - **snippets**: An optional dictionary of the form + {field: snippet_size} for snippet formatting + """ + + self.total = res[0] + self.duration = duration + self.docs = [] + + step = 1 + if hascontent: + step = step + 1 + if has_payload: + step = step + 1 + if with_scores: + step = step + 1 + + offset = 2 if with_scores else 1 + + for i in xrange(1, len(res), step): + id = to_string(res[i]) + payload = to_string(res[i + offset]) if has_payload else None + # fields_offset = 2 if has_payload else 1 + fields_offset = offset + 1 if has_payload else offset + score = float(res[i + 1]) if with_scores else None + + fields = {} + if hascontent: + fields = ( + dict( + dict( + izip( + map(to_string, res[i + fields_offset][::2]), + map(to_string, res[i + fields_offset][1::2]), + ) + ) + ) + if hascontent + else {} + ) + try: + del fields["id"] + except KeyError: + pass + + try: + fields["json"] = fields["$"] + del fields["$"] + except KeyError: + pass + + doc = ( + Document(id, score=score, payload=payload, **fields) + if with_scores + else Document(id, payload=payload, **fields) + ) + self.docs.append(doc) + + def __repr__(self): + return "Result{%d total, docs: %s}" % (self.total, self.docs) diff --git a/redis/commands/search/suggestion.py b/redis/commands/search/suggestion.py new file mode 100644 index 0000000..550c514 --- /dev/null +++ b/redis/commands/search/suggestion.py @@ -0,0 +1,54 @@ +from six.moves import xrange +from ._util import to_string + + +class Suggestion(object): + """ + Represents a single suggestion being sent or returned from the + autocomplete server + """ + + def __init__(self, string, score=1.0, payload=None): + self.string = to_string(string) + self.payload = to_string(payload) + self.score = score + + def __repr__(self): + return self.string + + +class SuggestionParser(object): + """ + Internal class used to parse results from the `SUGGET` command. + This needs to consume either 1, 2, or 3 values at a time from + the return value depending on what objects were requested + """ + + def __init__(self, with_scores, with_payloads, ret): + self.with_scores = with_scores + self.with_payloads = with_payloads + + if with_scores and with_payloads: + self.sugsize = 3 + self._scoreidx = 1 + self._payloadidx = 2 + elif with_scores: + self.sugsize = 2 + self._scoreidx = 1 + elif with_payloads: + self.sugsize = 2 + self._payloadidx = 1 + else: + self.sugsize = 1 + self._scoreidx = -1 + + self._sugs = ret + + def __iter__(self): + for i in xrange(0, len(self._sugs), self.sugsize): + ss = self._sugs[i] + score = float(self._sugs[i + self._scoreidx]) \ + if self.with_scores else 1.0 + payload = self._sugs[i + self._payloadidx] \ + if self.with_payloads else None + yield Suggestion(ss, score, payload) @@ -17,7 +17,6 @@ def devenv(c): cmd = 'tox -e devenv' for d in dockers: cmd += " --docker-dont-stop={}".format(d) - print("Running: {}".format(cmd)) run(cmd) diff --git a/tests/conftest.py b/tests/conftest.py index 9ca429d..47188df 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -13,6 +13,8 @@ REDIS_INFO = {} default_redis_url = "redis://localhost:6379/9" default_redismod_url = "redis://localhost:36379/9" +default_redismod_url = "redis://localhost:36379" + def pytest_addoption(parser): parser.addoption('--redis-url', default=default_redis_url, @@ -85,6 +87,7 @@ def skip_ifmodversion_lt(min_version: str, module_name: str): def _get_client(cls, request, single_connection_client=True, flushdb=True, + from_url=None, **kwargs): """ Helper for fixtures or tests that need a Redis client @@ -93,7 +96,10 @@ def _get_client(cls, request, single_connection_client=True, flushdb=True, ConnectionPool.from_url, keyword arguments to this function override values specified in the URL. """ - redis_url = request.config.getoption("--redis-url") + if from_url is None: + redis_url = request.config.getoption("--redis-url") + else: + redis_url = from_url url_options = parse_url(redis_url) url_options.update(kwargs) pool = redis.ConnectionPool(**url_options) @@ -115,9 +121,12 @@ def _get_client(cls, request, single_connection_client=True, flushdb=True, return client +# specifically set to the zero database, because creating +# an index on db != 0 raises a ResponseError in redis @pytest.fixture() -def modclient(request, port=36379, **kwargs): - with _get_client(redis.Redis, request, port=port, **kwargs) as client: +def modclient(request, **kwargs): + rmurl = request.config.getoption('--redismod-url') + with _get_client(redis.Redis, request, from_url=rmurl, **kwargs) as client: yield client diff --git a/tests/test_json.py b/tests/test_json.py index 96675f1..83fbf28 100644 --- a/tests/test_json.py +++ b/tests/test_json.py @@ -10,7 +10,7 @@ def client(modclient): return modclient -@pytest.mark.json +@pytest.mark.redismod def test_json_setbinarykey(client): d = {"hello": "world", b"some": "value"} with pytest.raises(TypeError): @@ -18,7 +18,7 @@ def test_json_setbinarykey(client): assert client.json().set("somekey", Path.rootPath(), d, decode_keys=True) -@pytest.mark.json +@pytest.mark.redismod def test_json_setgetdeleteforget(client): assert client.json().set("foo", Path.rootPath(), "bar") assert client.json().get("foo") == "bar" @@ -28,13 +28,13 @@ def test_json_setgetdeleteforget(client): assert client.exists("foo") == 0 -@pytest.mark.json +@pytest.mark.redismod def test_justaget(client): client.json().set("foo", Path.rootPath(), "bar") assert client.json().get("foo") == "bar" -@pytest.mark.json +@pytest.mark.redismod def test_json_get_jset(client): assert client.json().set("foo", Path.rootPath(), "bar") assert "bar" == client.json().get("foo") @@ -43,7 +43,7 @@ def test_json_get_jset(client): assert client.exists("foo") == 0 -@pytest.mark.json +@pytest.mark.redismod def test_nonascii_setgetdelete(client): assert client.json().set("notascii", Path.rootPath(), "hyvää-élève") is True @@ -52,7 +52,7 @@ def test_nonascii_setgetdelete(client): assert client.exists("notascii") == 0 -@pytest.mark.json +@pytest.mark.redismod def test_jsonsetexistentialmodifiersshouldsucceed(client): obj = {"foo": "bar"} assert client.json().set("obj", Path.rootPath(), obj) @@ -70,7 +70,7 @@ def test_jsonsetexistentialmodifiersshouldsucceed(client): client.json().set("obj", Path("foo"), "baz", nx=True, xx=True) -@pytest.mark.json +@pytest.mark.redismod def test_mgetshouldsucceed(client): client.json().set("1", Path.rootPath(), 1) client.json().set("2", Path.rootPath(), 2) @@ -79,7 +79,7 @@ def test_mgetshouldsucceed(client): assert e == r -@pytest.mark.json +@pytest.mark.redismod @skip_ifmodversion_lt("99.99.99", "ReJSON") # todo: update after the release def test_clearShouldSucceed(client): client.json().set("arr", Path.rootPath(), [0, 1, 2, 3, 4]) @@ -87,13 +87,13 @@ def test_clearShouldSucceed(client): assert [] == client.json().get("arr") -@pytest.mark.json +@pytest.mark.redismod def test_typeshouldsucceed(client): client.json().set("1", Path.rootPath(), 1) assert b"integer" == client.json().type("1") -@pytest.mark.json +@pytest.mark.redismod def test_numincrbyshouldsucceed(client): client.json().set("num", Path.rootPath(), 1) assert 2 == client.json().numincrby("num", Path.rootPath(), 1) @@ -101,7 +101,7 @@ def test_numincrbyshouldsucceed(client): assert 1.25 == client.json().numincrby("num", Path.rootPath(), -1.25) -@pytest.mark.json +@pytest.mark.redismod def test_nummultbyshouldsucceed(client): client.json().set("num", Path.rootPath(), 1) assert 2 == client.json().nummultby("num", Path.rootPath(), 2) @@ -109,7 +109,7 @@ def test_nummultbyshouldsucceed(client): assert 2.5 == client.json().nummultby("num", Path.rootPath(), 0.5) -@pytest.mark.json +@pytest.mark.redismod @skip_ifmodversion_lt("99.99.99", "ReJSON") # todo: update after the release def test_toggleShouldSucceed(client): client.json().set("bool", Path.rootPath(), False) @@ -121,20 +121,20 @@ def test_toggleShouldSucceed(client): client.json().toggle("num", Path.rootPath()) -@pytest.mark.json +@pytest.mark.redismod def test_strappendshouldsucceed(client): client.json().set("str", Path.rootPath(), "foo") assert 6 == client.json().strappend("str", "bar", Path.rootPath()) assert "foobar" == client.json().get("str", Path.rootPath()) -@pytest.mark.json +@pytest.mark.redismod def test_debug(client): client.json().set("str", Path.rootPath(), "foo") assert 24 == client.json().debug("str", Path.rootPath()) -@pytest.mark.json +@pytest.mark.redismod def test_strlenshouldsucceed(client): client.json().set("str", Path.rootPath(), "foo") assert 3 == client.json().strlen("str", Path.rootPath()) @@ -142,7 +142,7 @@ def test_strlenshouldsucceed(client): assert 6 == client.json().strlen("str", Path.rootPath()) -@pytest.mark.json +@pytest.mark.redismod def test_arrappendshouldsucceed(client): client.json().set("arr", Path.rootPath(), [1]) assert 2 == client.json().arrappend("arr", Path.rootPath(), 2) @@ -150,14 +150,14 @@ def test_arrappendshouldsucceed(client): assert 7 == client.json().arrappend("arr", Path.rootPath(), *[5, 6, 7]) -@pytest.mark.json +@pytest.mark.redismod def testArrIndexShouldSucceed(client): client.json().set("arr", Path.rootPath(), [0, 1, 2, 3, 4]) assert 1 == client.json().arrindex("arr", Path.rootPath(), 1) assert -1 == client.json().arrindex("arr", Path.rootPath(), 1, 2) -@pytest.mark.json +@pytest.mark.redismod def test_arrinsertshouldsucceed(client): client.json().set("arr", Path.rootPath(), [0, 4]) assert 5 - -client.json().arrinsert( @@ -173,13 +173,13 @@ def test_arrinsertshouldsucceed(client): assert [0, 1, 2, 3, 4] == client.json().get("arr") -@pytest.mark.json +@pytest.mark.redismod def test_arrlenshouldsucceed(client): client.json().set("arr", Path.rootPath(), [0, 1, 2, 3, 4]) assert 5 == client.json().arrlen("arr", Path.rootPath()) -@pytest.mark.json +@pytest.mark.redismod def test_arrpopshouldsucceed(client): client.json().set("arr", Path.rootPath(), [0, 1, 2, 3, 4]) assert 4 == client.json().arrpop("arr", Path.rootPath(), 4) @@ -189,14 +189,14 @@ def test_arrpopshouldsucceed(client): assert [1] == client.json().get("arr") -@pytest.mark.json +@pytest.mark.redismod def test_arrtrimshouldsucceed(client): client.json().set("arr", Path.rootPath(), [0, 1, 2, 3, 4]) assert 3 == client.json().arrtrim("arr", Path.rootPath(), 1, 3) assert [1, 2, 3] == client.json().get("arr") -@pytest.mark.json +@pytest.mark.redismod def test_respshouldsucceed(client): obj = {"foo": "bar", "baz": 1, "qaz": True} client.json().set("obj", Path.rootPath(), obj) @@ -205,7 +205,7 @@ def test_respshouldsucceed(client): assert client.json().resp("obj", Path("qaz")) -@pytest.mark.json +@pytest.mark.redismod def test_objkeysshouldsucceed(client): obj = {"foo": "bar", "baz": "qaz"} client.json().set("obj", Path.rootPath(), obj) @@ -216,7 +216,7 @@ def test_objkeysshouldsucceed(client): assert exp == keys -@pytest.mark.json +@pytest.mark.redismod def test_objlenshouldsucceed(client): obj = {"foo": "bar", "baz": "qaz"} client.json().set("obj", Path.rootPath(), obj) @@ -224,7 +224,7 @@ def test_objlenshouldsucceed(client): # @pytest.mark.pipeline -# @pytest.mark.json +# @pytest.mark.redismod # def test_pipelineshouldsucceed(client): # p = client.json().pipeline() # p.set("foo", Path.rootPath(), "bar") diff --git a/tests/test_search.py b/tests/test_search.py new file mode 100644 index 0000000..926b5ff --- /dev/null +++ b/tests/test_search.py @@ -0,0 +1,1219 @@ +import pytest +import redis +import bz2 +import csv +import time +import os + +from io import TextIOWrapper +from .conftest import skip_ifmodversion_lt, default_redismod_url +from redis import Redis + +import redis.commands.search +from redis.commands.json.path import Path +from redis.commands.search import Search +from redis.commands.search.field import ( + GeoField, + NumericField, + TagField, + TextField +) +from redis.commands.search.query import ( + GeoFilter, + NumericFilter, + Query +) +from redis.commands.search.result import Result +from redis.commands.search.indexDefinition import IndexDefinition, IndexType +from redis.commands.search.suggestion import Suggestion +import redis.commands.search.aggregation as aggregations +import redis.commands.search.reducers as reducers + +WILL_PLAY_TEXT = ( + os.path.abspath( + os.path.join( + os.path.dirname(__file__), + "testdata", + "will_play_text.csv.bz2" + ) + ) +) + +TITLES_CSV = ( + os.path.abspath( + os.path.join( + os.path.dirname(__file__), + "testdata", + "titles.csv" + ) + ) +) + + +def waitForIndex(env, idx, timeout=None): + delay = 0.1 + while True: + res = env.execute_command("ft.info", idx) + try: + res.index("indexing") + except ValueError: + break + + if int(res[res.index("indexing") + 1]) == 0: + break + + time.sleep(delay) + if timeout is not None: + timeout -= delay + if timeout <= 0: + break + + +def getClient(): + """ + Gets a client client attached to an index name which is ready to be + created + """ + rc = Redis.from_url(default_redismod_url, decode_responses=True) + return rc + + +def createIndex(client, num_docs=100, definition=None): + try: + client.create_index( + (TextField("play", weight=5.0), + TextField("txt"), + NumericField("chapter")), + definition=definition, + ) + except redis.ResponseError: + client.dropindex(delete_documents=True) + return createIndex(client, num_docs=num_docs, definition=definition) + + chapters = {} + bzfp = TextIOWrapper(bz2.BZ2File(WILL_PLAY_TEXT), encoding="utf8") + + r = csv.reader(bzfp, delimiter=";") + for n, line in enumerate(r): + + play, chapter, _, text = \ + line[1], line[2], line[4], line[5] + + key = "{}:{}".format(play, chapter).lower() + d = chapters.setdefault(key, {}) + d["play"] = play + d["txt"] = d.get("txt", "") + " " + text + d["chapter"] = int(chapter or 0) + if len(chapters) == num_docs: + break + + indexer = client.batch_indexer(chunk_size=50) + assert isinstance(indexer, Search.BatchIndexer) + assert 50 == indexer.chunk_size + + for key, doc in chapters.items(): + indexer.add_document(key, **doc) + indexer.commit() + + +# override the default module client, search requires both db=0, and text +@pytest.fixture +def modclient(): + return Redis.from_url(default_redismod_url, db=0, decode_responses=True) + + +@pytest.fixture +def client(modclient): + modclient.flushdb() + return modclient + + +@pytest.mark.redismod +def test_client(client): + num_docs = 500 + createIndex(client.ft(), num_docs=num_docs) + waitForIndex(client, "idx") + # verify info + info = client.ft().info() + for k in [ + "index_name", + "index_options", + "attributes", + "num_docs", + "max_doc_id", + "num_terms", + "num_records", + "inverted_sz_mb", + "offset_vectors_sz_mb", + "doc_table_size_mb", + "key_table_size_mb", + "records_per_doc_avg", + "bytes_per_record_avg", + "offsets_per_term_avg", + "offset_bits_per_record_avg", + ]: + assert k in info + + assert client.ft().index_name == info["index_name"] + assert num_docs == int(info["num_docs"]) + + res = client.ft().search("henry iv") + assert isinstance(res, Result) + assert 225 == res.total + assert 10 == len(res.docs) + assert res.duration > 0 + + for doc in res.docs: + assert doc.id + assert doc.play == "Henry IV" + assert len(doc.txt) > 0 + + # test no content + res = client.ft().search(Query("king").no_content()) + assert 194 == res.total + assert 10 == len(res.docs) + for doc in res.docs: + assert "txt" not in doc.__dict__ + assert "play" not in doc.__dict__ + + # test verbatim vs no verbatim + total = client.ft().search(Query("kings").no_content()).total + vtotal = client.ft().search(Query("kings").no_content().verbatim()).total + assert total > vtotal + + # test in fields + txt_total = ( + client.ft().search( + Query("henry").no_content().limit_fields("txt")).total + ) + play_total = ( + client.ft().search( + Query("henry").no_content().limit_fields("play")).total + ) + both_total = ( + client.ft() + .search(Query("henry").no_content().limit_fields("play", "txt")) + .total + ) + assert 129 == txt_total + assert 494 == play_total + assert 494 == both_total + + # test load_document + doc = client.ft().load_document("henry vi part 3:62") + assert doc is not None + assert "henry vi part 3:62" == doc.id + assert doc.play == "Henry VI Part 3" + assert len(doc.txt) > 0 + + # test in-keys + ids = [x.id for x in client.ft().search(Query("henry")).docs] + assert 10 == len(ids) + subset = ids[:5] + docs = client.ft().search(Query("henry").limit_ids(*subset)) + assert len(subset) == docs.total + ids = [x.id for x in docs.docs] + assert set(ids) == set(subset) + + # test slop and in order + assert 193 == client.ft().search(Query("henry king")).total + assert 3 == client.ft().search( + Query("henry king").slop(0).in_order()).total + assert 52 == client.ft().search( + Query("king henry").slop(0).in_order()).total + assert 53 == client.ft().search(Query("henry king").slop(0)).total + assert 167 == client.ft().search(Query("henry king").slop(100)).total + + # test delete document + client.ft().add_document("doc-5ghs2", play="Death of a Salesman") + res = client.ft().search(Query("death of a salesman")) + assert 1 == res.total + + assert 1 == client.ft().delete_document("doc-5ghs2") + res = client.ft().search(Query("death of a salesman")) + assert 0 == res.total + assert 0 == client.ft().delete_document("doc-5ghs2") + + client.ft().add_document("doc-5ghs2", play="Death of a Salesman") + res = client.ft().search(Query("death of a salesman")) + assert 1 == res.total + client.ft().delete_document("doc-5ghs2") + + +@pytest.mark.redismod +@skip_ifmodversion_lt("2.2.0", "search") +def test_payloads(client): + client.ft().create_index((TextField("txt"),)) + + client.ft().add_document("doc1", payload="foo baz", txt="foo bar") + client.ft().add_document("doc2", txt="foo bar") + + q = Query("foo bar").with_payloads() + res = client.ft().search(q) + assert 2 == res.total + assert "doc1" == res.docs[0].id + assert "doc2" == res.docs[1].id + assert "foo baz" == res.docs[0].payload + assert res.docs[1].payload is None + + +@pytest.mark.redismod +def test_scores(client): + client.ft().create_index((TextField("txt"),)) + + client.ft().add_document("doc1", txt="foo baz") + client.ft().add_document("doc2", txt="foo bar") + + q = Query("foo ~bar").with_scores() + res = client.ft().search(q) + assert 2 == res.total + assert "doc2" == res.docs[0].id + assert 3.0 == res.docs[0].score + assert "doc1" == res.docs[1].id + # todo: enable once new RS version is tagged + # self.assertEqual(0.2, res.docs[1].score) + + +@pytest.mark.redismod +def test_replace(client): + client.ft().create_index((TextField("txt"),)) + + client.ft().add_document("doc1", txt="foo bar") + client.ft().add_document("doc2", txt="foo bar") + waitForIndex(client, "idx") + + res = client.ft().search("foo bar") + assert 2 == res.total + client.ft().add_document( + "doc1", + replace=True, + txt="this is a replaced doc" + ) + + res = client.ft().search("foo bar") + assert 1 == res.total + assert "doc2" == res.docs[0].id + + res = client.ft().search("replaced doc") + assert 1 == res.total + assert "doc1" == res.docs[0].id + + +@pytest.mark.redismod +def test_stopwords(client): + client.ft().create_index( + (TextField("txt"),), + stopwords=["foo", "bar", "baz"] + ) + client.ft().add_document("doc1", txt="foo bar") + client.ft().add_document("doc2", txt="hello world") + waitForIndex(client, "idx") + + q1 = Query("foo bar").no_content() + q2 = Query("foo bar hello world").no_content() + res1, res2 = client.ft().search(q1), client.ft().search(q2) + assert 0 == res1.total + assert 1 == res2.total + + +@pytest.mark.redismod +def test_filters(client): + client.ft().create_index( + (TextField("txt"), + NumericField("num"), + GeoField("loc")) + ) + client.ft().add_document( + "doc1", + txt="foo bar", + num=3.141, + loc="-0.441,51.458" + ) + client.ft().add_document("doc2", txt="foo baz", num=2, loc="-0.1,51.2") + + waitForIndex(client, "idx") + # Test numerical filter + q1 = Query("foo").add_filter(NumericFilter("num", 0, 2)).no_content() + q2 = ( + Query("foo") + .add_filter( + NumericFilter("num", 2, NumericFilter.INF, minExclusive=True)) + .no_content() + ) + res1, res2 = client.ft().search(q1), client.ft().search(q2) + + assert 1 == res1.total + assert 1 == res2.total + assert "doc2" == res1.docs[0].id + assert "doc1" == res2.docs[0].id + + # Test geo filter + q1 = Query("foo").add_filter( + GeoFilter("loc", -0.44, 51.45, 10)).no_content() + q2 = Query("foo").add_filter( + GeoFilter("loc", -0.44, 51.45, 100)).no_content() + res1, res2 = client.ft().search(q1), client.ft().search(q2) + + assert 1 == res1.total + assert 2 == res2.total + assert "doc1" == res1.docs[0].id + + # Sort results, after RDB reload order may change + res = [res2.docs[0].id, res2.docs[1].id] + res.sort() + assert ["doc1", "doc2"] == res + + +@pytest.mark.redismod +def test_payloads_with_no_content(client): + client.ft().create_index((TextField("txt"),)) + client.ft().add_document("doc1", payload="foo baz", txt="foo bar") + client.ft().add_document("doc2", payload="foo baz2", txt="foo bar") + + q = Query("foo bar").with_payloads().no_content() + res = client.ft().search(q) + assert 2 == len(res.docs) + + +@pytest.mark.redismod +def test_sort_by(client): + client.ft().create_index( + (TextField("txt"), + NumericField("num", sortable=True)) + ) + client.ft().add_document("doc1", txt="foo bar", num=1) + client.ft().add_document("doc2", txt="foo baz", num=2) + client.ft().add_document("doc3", txt="foo qux", num=3) + + # Test sort + q1 = Query("foo").sort_by("num", asc=True).no_content() + q2 = Query("foo").sort_by("num", asc=False).no_content() + res1, res2 = client.ft().search(q1), client.ft().search(q2) + + assert 3 == res1.total + assert "doc1" == res1.docs[0].id + assert "doc2" == res1.docs[1].id + assert "doc3" == res1.docs[2].id + assert 3 == res2.total + assert "doc1" == res2.docs[2].id + assert "doc2" == res2.docs[1].id + assert "doc3" == res2.docs[0].id + + +@pytest.mark.redismod +@skip_ifmodversion_lt("2.0.0", "search") +def test_drop_index(): + """ + Ensure the index gets dropped by data remains by default + """ + for x in range(20): + for keep_docs in [[True, {}], [False, {"name": "haveit"}]]: + idx = "HaveIt" + index = getClient() + index.hset("index:haveit", mapping={"name": "haveit"}) + idef = IndexDefinition(prefix=["index:"]) + index.ft(idx).create_index((TextField("name"),), definition=idef) + waitForIndex(index, idx) + index.ft(idx).dropindex(delete_documents=keep_docs[0]) + i = index.hgetall("index:haveit") + assert i == keep_docs[1] + + +@pytest.mark.redismod +def test_example(client): + # Creating the index definition and schema + client.ft().create_index( + (TextField("title", weight=5.0), + TextField("body")) + ) + + # Indexing a document + client.ft().add_document( + "doc1", + title="RediSearch", + body="Redisearch impements a search engine on top of redis", + ) + + # Searching with complex parameters: + q = Query("search engine").verbatim().no_content().paging(0, 5) + + res = client.ft().search(q) + assert res is not None + + +@pytest.mark.redismod +def test_auto_complete(client): + n = 0 + with open(TITLES_CSV) as f: + cr = csv.reader(f) + + for row in cr: + n += 1 + term, score = row[0], float(row[1]) + assert n == client.ft().sugadd("ac", Suggestion(term, score=score)) + + assert n == client.ft().suglen("ac") + ret = client.ft().sugget("ac", "bad", with_scores=True) + assert 2 == len(ret) + assert "badger" == ret[0].string + assert isinstance(ret[0].score, float) + assert 1.0 != ret[0].score + assert "badalte rishtey" == ret[1].string + assert isinstance(ret[1].score, float) + assert 1.0 != ret[1].score + + ret = client.ft().sugget("ac", "bad", fuzzy=True, num=10) + assert 10 == len(ret) + assert 1.0 == ret[0].score + strs = {x.string for x in ret} + + for sug in strs: + assert 1 == client.ft().sugdel("ac", sug) + # make sure a second delete returns 0 + for sug in strs: + assert 0 == client.ft().sugdel("ac", sug) + + # make sure they were actually deleted + ret2 = client.ft().sugget("ac", "bad", fuzzy=True, num=10) + for sug in ret2: + assert sug.string not in strs + + # Test with payload + client.ft().sugadd("ac", Suggestion("pay1", payload="pl1")) + client.ft().sugadd("ac", Suggestion("pay2", payload="pl2")) + client.ft().sugadd("ac", Suggestion("pay3", payload="pl3")) + + sugs = client.ft().sugget( + "ac", + "pay", + with_payloads=True, + with_scores=True + ) + assert 3 == len(sugs) + for sug in sugs: + assert sug.payload + assert sug.payload.startswith("pl") + + +@pytest.mark.redismod +def test_no_index(client): + client.ft().create_index( + ( + TextField("field"), + TextField("text", no_index=True, sortable=True), + NumericField("numeric", no_index=True, sortable=True), + GeoField("geo", no_index=True, sortable=True), + TagField("tag", no_index=True, sortable=True), + ) + ) + + client.ft().add_document( + "doc1", field="aaa", text="1", numeric="1", geo="1,1", tag="1" + ) + client.ft().add_document( + "doc2", field="aab", text="2", numeric="2", geo="2,2", tag="2" + ) + waitForIndex(client, "idx") + + res = client.ft().search(Query("@text:aa*")) + assert 0 == res.total + + res = client.ft().search(Query("@field:aa*")) + assert 2 == res.total + + res = client.ft().search(Query("*").sort_by("text", asc=False)) + assert 2 == res.total + assert "doc2" == res.docs[0].id + + res = client.ft().search(Query("*").sort_by("text", asc=True)) + assert "doc1" == res.docs[0].id + + res = client.ft().search(Query("*").sort_by("numeric", asc=True)) + assert "doc1" == res.docs[0].id + + res = client.ft().search(Query("*").sort_by("geo", asc=True)) + assert "doc1" == res.docs[0].id + + res = client.ft().search(Query("*").sort_by("tag", asc=True)) + assert "doc1" == res.docs[0].id + + # Ensure exception is raised for non-indexable, non-sortable fields + with pytest.raises(Exception): + TextField("name", no_index=True, sortable=False) + with pytest.raises(Exception): + NumericField("name", no_index=True, sortable=False) + with pytest.raises(Exception): + GeoField("name", no_index=True, sortable=False) + with pytest.raises(Exception): + TagField("name", no_index=True, sortable=False) + + +@pytest.mark.redismod +def test_partial(client): + client.ft().create_index( + (TextField("f1"), + TextField("f2"), + TextField("f3")) + ) + client.ft().add_document("doc1", f1="f1_val", f2="f2_val") + client.ft().add_document("doc2", f1="f1_val", f2="f2_val") + client.ft().add_document("doc1", f3="f3_val", partial=True) + client.ft().add_document("doc2", f3="f3_val", replace=True) + waitForIndex(client, "idx") + + # Search for f3 value. All documents should have it + res = client.ft().search("@f3:f3_val") + assert 2 == res.total + + # Only the document updated with PARTIAL should still have f1 and f2 values + res = client.ft().search("@f3:f3_val @f2:f2_val @f1:f1_val") + assert 1 == res.total + + +@pytest.mark.redismod +def test_no_create(client): + client.ft().create_index( + (TextField("f1"), + TextField("f2"), + TextField("f3")) + ) + client.ft().add_document("doc1", f1="f1_val", f2="f2_val") + client.ft().add_document("doc2", f1="f1_val", f2="f2_val") + client.ft().add_document("doc1", f3="f3_val", no_create=True) + client.ft().add_document("doc2", f3="f3_val", no_create=True, partial=True) + waitForIndex(client, "idx") + + # Search for f3 value. All documents should have it + res = client.ft().search("@f3:f3_val") + assert 2 == res.total + + # Only the document updated with PARTIAL should still have f1 and f2 values + res = client.ft().search("@f3:f3_val @f2:f2_val @f1:f1_val") + assert 1 == res.total + + with pytest.raises(redis.ResponseError): + client.ft().add_document( + "doc3", + f2="f2_val", + f3="f3_val", + no_create=True + ) + + +@pytest.mark.redismod +def test_explain(client): + client.ft().create_index( + (TextField("f1"), + TextField("f2"), + TextField("f3")) + ) + res = client.ft().explain("@f3:f3_val @f2:f2_val @f1:f1_val") + assert res + + +@pytest.mark.redismod +def test_summarize(client): + createIndex(client.ft()) + waitForIndex(client, "idx") + + q = Query("king henry").paging(0, 1) + q.highlight(fields=("play", "txt"), tags=("<b>", "</b>")) + q.summarize("txt") + + doc = sorted(client.ft().search(q).docs)[0] + assert "<b>Henry</b> IV" == doc.play + assert ( + "ACT I SCENE I. London. The palace. Enter <b>KING</b> <b>HENRY</b>, LORD JOHN OF LANCASTER, the EARL of WESTMORELAND, SIR... " # noqa + == doc.txt + ) + + q = Query("king henry").paging(0, 1).summarize().highlight() + + doc = sorted(client.ft().search(q).docs)[0] + assert "<b>Henry</b> ... " == doc.play + assert ( + "ACT I SCENE I. London. The palace. Enter <b>KING</b> <b>HENRY</b>, LORD JOHN OF LANCASTER, the EARL of WESTMORELAND, SIR... " # noqa + == doc.txt + ) + + +@pytest.mark.redismod +@skip_ifmodversion_lt("2.0.0", "search") +def test_alias(): + index1 = getClient() + index2 = getClient() + + index1.hset("index1:lonestar", mapping={"name": "lonestar"}) + index2.hset("index2:yogurt", mapping={"name": "yogurt"}) + + if os.environ.get("GITHUB_WORKFLOW", None) is not None: + time.sleep(2) + else: + time.sleep(5) + + def1 = IndexDefinition(prefix=["index1:"], score_field="name") + def2 = IndexDefinition(prefix=["index2:"], score_field="name") + + ftindex1 = index1.ft("testAlias") + ftindex2 = index1.ft("testAlias2") + ftindex1.create_index((TextField("name"),), definition=def1) + ftindex2.create_index((TextField("name"),), definition=def2) + + # CI is slower + try: + res = ftindex1.search("*").docs[0] + except IndexError: + time.sleep(5) + res = ftindex1.search("*").docs[0] + assert "index1:lonestar" == res.id + + # create alias and check for results + ftindex1.aliasadd("spaceballs") + alias_client = getClient().ft("spaceballs") + res = alias_client.search("*").docs[0] + assert "index1:lonestar" == res.id + + # Throw an exception when trying to add an alias that already exists + with pytest.raises(Exception): + ftindex2.aliasadd("spaceballs") + + # update alias and ensure new results + ftindex2.aliasupdate("spaceballs") + alias_client2 = getClient().ft("spaceballs") + res = alias_client2.search("*").docs[0] + assert "index2:yogurt" == res.id + + ftindex2.aliasdel("spaceballs") + with pytest.raises(Exception): + alias_client2.search("*").docs[0] + + +@pytest.mark.redismod +def test_alias_basic(): + # Creating a client with one index + getClient().flushdb() + index1 = getClient().ft("testAlias") + + index1.create_index((TextField("txt"),)) + index1.add_document("doc1", txt="text goes here") + + index2 = getClient().ft("testAlias2") + index2.create_index((TextField("txt"),)) + index2.add_document("doc2", txt="text goes here") + + # add the actual alias and check + index1.aliasadd("myalias") + alias_client = getClient().ft("myalias") + res = sorted(alias_client.search("*").docs, key=lambda x: x.id) + assert "doc1" == res[0].id + + # Throw an exception when trying to add an alias that already exists + with pytest.raises(Exception): + index2.aliasadd("myalias") + + # update the alias and ensure we get doc2 + index2.aliasupdate("myalias") + alias_client2 = getClient().ft("myalias") + res = sorted(alias_client2.search("*").docs, key=lambda x: x.id) + assert "doc1" == res[0].id + + # delete the alias and expect an error if we try to query again + index2.aliasdel("myalias") + with pytest.raises(Exception): + _ = alias_client2.search("*").docs[0] + + +@pytest.mark.redismod +def test_tags(client): + client.ft().create_index((TextField("txt"), TagField("tags"))) + tags = "foo,foo bar,hello;world" + tags2 = "soba,ramen" + + client.ft().add_document("doc1", txt="fooz barz", tags=tags) + client.ft().add_document("doc2", txt="noodles", tags=tags2) + waitForIndex(client, "idx") + + q = Query("@tags:{foo}") + res = client.ft().search(q) + assert 1 == res.total + + q = Query("@tags:{foo bar}") + res = client.ft().search(q) + assert 1 == res.total + + q = Query("@tags:{foo\\ bar}") + res = client.ft().search(q) + assert 1 == res.total + + q = Query("@tags:{hello\\;world}") + res = client.ft().search(q) + assert 1 == res.total + + q2 = client.ft().tagvals("tags") + assert (tags.split(",") + tags2.split(",")).sort() == q2.sort() + + +@pytest.mark.redismod +def test_textfield_sortable_nostem(client): + # Creating the index definition with sortable and no_stem + client.ft().create_index((TextField("txt", sortable=True, no_stem=True),)) + + # Now get the index info to confirm its contents + response = client.ft().info() + assert "SORTABLE" in response["attributes"][0] + assert "NOSTEM" in response["attributes"][0] + + +@pytest.mark.redismod +def test_alter_schema_add(client): + # Creating the index definition and schema + client.ft().create_index(TextField("title")) + + # Using alter to add a field + client.ft().alter_schema_add(TextField("body")) + + # Indexing a document + client.ft().add_document( + "doc1", title="MyTitle", body="Some content only in the body" + ) + + # Searching with parameter only in the body (the added field) + q = Query("only in the body") + + # Ensure we find the result searching on the added body field + res = client.ft().search(q) + assert 1 == res.total + + +@pytest.mark.redismod +def test_spell_check(client): + client.ft().create_index((TextField("f1"), TextField("f2"))) + + client.ft().add_document( + "doc1", + f1="some valid content", + f2="this is sample text" + ) + client.ft().add_document("doc2", f1="very important", f2="lorem ipsum") + waitForIndex(client, "idx") + + # test spellcheck + res = client.ft().spellcheck("impornant") + assert "important" == res["impornant"][0]["suggestion"] + + res = client.ft().spellcheck("contnt") + assert "content" == res["contnt"][0]["suggestion"] + + # test spellcheck with Levenshtein distance + res = client.ft().spellcheck("vlis") + assert res == {} + res = client.ft().spellcheck("vlis", distance=2) + assert "valid" == res["vlis"][0]["suggestion"] + + # test spellcheck include + client.ft().dict_add("dict", "lore", "lorem", "lorm") + res = client.ft().spellcheck("lorm", include="dict") + assert len(res["lorm"]) == 3 + assert ( + res["lorm"][0]["suggestion"], + res["lorm"][1]["suggestion"], + res["lorm"][2]["suggestion"], + ) == ("lorem", "lore", "lorm") + assert (res["lorm"][0]["score"], res["lorm"][1]["score"]) == ("0.5", "0") + + # test spellcheck exclude + res = client.ft().spellcheck("lorm", exclude="dict") + assert res == {} + + +@pytest.mark.redismod +def test_dict_operations(client): + client.ft().create_index((TextField("f1"), TextField("f2"))) + # Add three items + res = client.ft().dict_add("custom_dict", "item1", "item2", "item3") + assert 3 == res + + # Remove one item + res = client.ft().dict_del("custom_dict", "item2") + assert 1 == res + + # Dump dict and inspect content + res = client.ft().dict_dump("custom_dict") + assert ["item1", "item3"] == res + + # Remove rest of the items before reload + client.ft().dict_del("custom_dict", *res) + + +@pytest.mark.redismod +def test_phonetic_matcher(client): + client.ft().create_index((TextField("name"),)) + client.ft().add_document("doc1", name="Jon") + client.ft().add_document("doc2", name="John") + + res = client.ft().search(Query("Jon")) + assert 1 == len(res.docs) + assert "Jon" == res.docs[0].name + + # Drop and create index with phonetic matcher + client.flushdb() + + client.ft().create_index((TextField("name", phonetic_matcher="dm:en"),)) + client.ft().add_document("doc1", name="Jon") + client.ft().add_document("doc2", name="John") + + res = client.ft().search(Query("Jon")) + assert 2 == len(res.docs) + assert ["John", "Jon"] == sorted([d.name for d in res.docs]) + + +@pytest.mark.redismod +def test_scorer(client): + client.ft().create_index((TextField("description"),)) + + client.ft().add_document( + "doc1", description="The quick brown fox jumps over the lazy dog" + ) + client.ft().add_document( + "doc2", + description="Quick alice was beginning to get very tired of sitting by her quick sister on the bank, and of having nothing to do.", # noqa + ) + + # default scorer is TFIDF + res = client.ft().search(Query("quick").with_scores()) + assert 1.0 == res.docs[0].score + res = client.ft().search(Query("quick").scorer("TFIDF").with_scores()) + assert 1.0 == res.docs[0].score + res = client.ft().search( + Query("quick").scorer("TFIDF.DOCNORM").with_scores()) + assert 0.1111111111111111 == res.docs[0].score + res = client.ft().search(Query("quick").scorer("BM25").with_scores()) + assert 0.17699114465425977 == res.docs[0].score + res = client.ft().search(Query("quick").scorer("DISMAX").with_scores()) + assert 2.0 == res.docs[0].score + res = client.ft().search(Query("quick").scorer("DOCSCORE").with_scores()) + assert 1.0 == res.docs[0].score + res = client.ft().search(Query("quick").scorer("HAMMING").with_scores()) + assert 0.0 == res.docs[0].score + + +@pytest.mark.redismod +def test_get(client): + client.ft().create_index((TextField("f1"), TextField("f2"))) + + assert [None] == client.ft().get("doc1") + assert [None, None] == client.ft().get("doc2", "doc1") + + client.ft().add_document( + "doc1", f1="some valid content dd1", f2="this is sample text ff1" + ) + client.ft().add_document( + "doc2", f1="some valid content dd2", f2="this is sample text ff2" + ) + + assert [ + ["f1", "some valid content dd2", "f2", "this is sample text ff2"] + ] == client.ft().get("doc2") + assert [ + ["f1", "some valid content dd1", "f2", "this is sample text ff1"], + ["f1", "some valid content dd2", "f2", "this is sample text ff2"], + ] == client.ft().get("doc1", "doc2") + + +@pytest.mark.redismod +@skip_ifmodversion_lt("2.2.0", "search") +def test_config(client): + assert client.ft().config_set("TIMEOUT", "100") + with pytest.raises(redis.ResponseError): + client.ft().config_set("TIMEOUT", "null") + res = client.ft().config_get("*") + assert "100" == res["TIMEOUT"] + res = client.ft().config_get("TIMEOUT") + assert "100" == res["TIMEOUT"] + + +@pytest.mark.redismod +def test_aggregations(client): + # Creating the index definition and schema + client.ft().create_index( + ( + NumericField("random_num"), + TextField("title"), + TextField("body"), + TextField("parent"), + ) + ) + + # Indexing a document + client.ft().add_document( + "search", + title="RediSearch", + body="Redisearch impements a search engine on top of redis", + parent="redis", + random_num=10, + ) + client.ft().add_document( + "ai", + title="RedisAI", + body="RedisAI executes Deep Learning/Machine Learning models and managing their data.", # noqa + parent="redis", + random_num=3, + ) + client.ft().add_document( + "json", + title="RedisJson", + body="RedisJSON implements ECMA-404 The JSON Data Interchange Standard as a native data type.", # noqa + parent="redis", + random_num=8, + ) + + req = aggregations.AggregateRequest("redis").group_by( + "@parent", + reducers.count(), + reducers.count_distinct("@title"), + reducers.count_distinctish("@title"), + reducers.sum("@random_num"), + reducers.min("@random_num"), + reducers.max("@random_num"), + reducers.avg("@random_num"), + reducers.stddev("random_num"), + reducers.quantile("@random_num", 0.5), + reducers.tolist("@title"), + reducers.first_value("@title"), + reducers.random_sample("@title", 2), + ) + + res = client.ft().aggregate(req) + + res = res.rows[0] + assert len(res) == 26 + assert "redis" == res[1] + assert "3" == res[3] + assert "3" == res[5] + assert "3" == res[7] + assert "21" == res[9] + assert "3" == res[11] + assert "10" == res[13] + assert "7" == res[15] + assert "3.60555127546" == res[17] + assert "10" == res[19] + assert ["RediSearch", "RedisAI", "RedisJson"] == res[21] + assert "RediSearch" == res[23] + assert 2 == len(res[25]) + + +@pytest.mark.redismod +@skip_ifmodversion_lt("2.0.0", "search") +def test_index_definition(client): + """ + Create definition and test its args + """ + with pytest.raises(RuntimeError): + IndexDefinition(prefix=["hset:", "henry"], index_type="json") + + definition = IndexDefinition( + prefix=["hset:", "henry"], + filter="@f1==32", + language="English", + language_field="play", + score_field="chapter", + score=0.5, + payload_field="txt", + index_type=IndexType.JSON, + ) + + assert [ + "ON", + "JSON", + "PREFIX", + 2, + "hset:", + "henry", + "FILTER", + "@f1==32", + "LANGUAGE_FIELD", + "play", + "LANGUAGE", + "English", + "SCORE_FIELD", + "chapter", + "SCORE", + 0.5, + "PAYLOAD_FIELD", + "txt", + ] == definition.args + + createIndex(client.ft(), num_docs=500, definition=definition) + + +@pytest.mark.redismod +@skip_ifmodversion_lt("2.0.0", "search") +def test_create_client_definition(client): + """ + Create definition with no index type provided, + and use hset to test the client definition (the default is HASH). + """ + definition = IndexDefinition(prefix=["hset:", "henry"]) + createIndex(client.ft(), num_docs=500, definition=definition) + + info = client.ft().info() + assert 494 == int(info["num_docs"]) + + client.ft().client.hset("hset:1", "f1", "v1") + info = client.ft().info() + assert 495 == int(info["num_docs"]) + + +@pytest.mark.redismod +@skip_ifmodversion_lt("2.0.0", "search") +def test_create_client_definition_hash(client): + """ + Create definition with IndexType.HASH as index type (ON HASH), + and use hset to test the client definition. + """ + definition = IndexDefinition( + prefix=["hset:", "henry"], + index_type=IndexType.HASH + ) + createIndex(client.ft(), num_docs=500, definition=definition) + + info = client.ft().info() + assert 494 == int(info["num_docs"]) + + client.ft().client.hset("hset:1", "f1", "v1") + info = client.ft().info() + assert 495 == int(info["num_docs"]) + + +@pytest.mark.redismod +@skip_ifmodversion_lt("2.2.0", "search") +def test_create_client_definition_json(client): + """ + Create definition with IndexType.JSON as index type (ON JSON), + and use json client to test it. + """ + definition = IndexDefinition(prefix=["king:"], index_type=IndexType.JSON) + client.ft().create_index((TextField("$.name"),), definition=definition) + + client.json().set("king:1", Path.rootPath(), {"name": "henry"}) + client.json().set("king:2", Path.rootPath(), {"name": "james"}) + + res = client.ft().search("henry") + assert res.docs[0].id == "king:1" + assert res.docs[0].payload is None + assert res.docs[0].json == '{"name":"henry"}' + assert res.total == 1 + + +@pytest.mark.redismod +@skip_ifmodversion_lt("2.2.0", "search") +def test_fields_as_name(client): + # create index + SCHEMA = ( + TextField("$.name", sortable=True, as_name="name"), + NumericField("$.age", as_name="just_a_number"), + ) + definition = IndexDefinition(index_type=IndexType.JSON) + client.ft().create_index(SCHEMA, definition=definition) + + # insert json data + res = client.json().set( + "doc:1", + Path.rootPath(), + {"name": "Jon", "age": 25} + ) + assert res + + total = client.ft().search( + Query("Jon").return_fields("name", "just_a_number")).docs + assert 1 == len(total) + assert "doc:1" == total[0].id + assert "Jon" == total[0].name + assert "25" == total[0].just_a_number + + +@pytest.mark.redismod +@skip_ifmodversion_lt("2.2.0", "search") +def test_search_return_fields(client): + res = client.json().set( + "doc:1", + Path.rootPath(), + {"t": "riceratops", "t2": "telmatosaurus", "n": 9072, "flt": 97.2}, + ) + assert res + + # create index on + definition = IndexDefinition(index_type=IndexType.JSON) + SCHEMA = ( + TextField("$.t"), + NumericField("$.flt"), + ) + client.ft().create_index(SCHEMA, definition=definition) + waitForIndex(client, "idx") + + total = client.ft().search( + Query("*").return_field("$.t", as_field="txt")).docs + assert 1 == len(total) + assert "doc:1" == total[0].id + assert "riceratops" == total[0].txt + + total = client.ft().search( + Query("*").return_field("$.t2", as_field="txt")).docs + assert 1 == len(total) + assert "doc:1" == total[0].id + assert "telmatosaurus" == total[0].txt + + +@pytest.mark.redismod +def test_synupdate(client): + definition = IndexDefinition(index_type=IndexType.HASH) + client.ft().create_index( + ( + TextField("title"), + TextField("body"), + ), + definition=definition, + ) + + client.ft().synupdate("id1", True, "boy", "child", "offspring") + client.ft().add_document( + "doc1", + title="he is a baby", + body="this is a test") + + client.ft().synupdate("id1", True, "baby") + client.ft().add_document( + "doc2", + title="he is another baby", + body="another test" + ) + + res = client.ft().search(Query("child").expander("SYNONYM")) + assert res.docs[0].id == "doc2" + assert res.docs[0].title == "he is another baby" + assert res.docs[0].body == "another test" + + +@pytest.mark.redismod +def test_syndump(client): + definition = IndexDefinition(index_type=IndexType.HASH) + client.ft().create_index( + ( + TextField("title"), + TextField("body"), + ), + definition=definition, + ) + + client.ft().synupdate("id1", False, "boy", "child", "offspring") + client.ft().synupdate("id2", False, "baby", "child") + client.ft().synupdate("id3", False, "tree", "wood") + res = client.ft().syndump() + assert res == { + "boy": ["id1"], + "tree": ["id3"], + "wood": ["id3"], + "child": ["id1", "id2"], + "baby": ["id2"], + "offspring": ["id1"], + } diff --git a/tests/testdata/titles.csv b/tests/testdata/titles.csv new file mode 100644 index 0000000..6428dd2 --- /dev/null +++ b/tests/testdata/titles.csv @@ -0,0 +1,4861 @@ +bhoj shala,1 +radhika balakrishnan,1 +ltm,1 +sterlite energy,1 +troll doll,11 +sonnontio,1 +nickelodeon netherlands kids choice awards,1 +jamaica national basketball team,5 +clan mackenzie,1 +secure attention key,3 +template talk indo pakistani war of 1971,1 +hassan firouzabadi,2 +carter alan,1 +alan levy,1 +tim severin,2 +faux pas derived from chinese pronunciation,1 +jruby,3 +tobias nielsén,1 +avro 571 buffalo,1 +treasury stock,17 +שלום,10 +oxygen 19,1 +ntru,4 +tennis racquet,1 +place of birth,4 +council of canadians,1 +urshu,1 +american hotel,1 +dow corning corporation,3 +language based learning disability,3 +meri aashiqui tum se hi,30 +specificity,9 +edward l hedden,1 +pelli chesukundam,2 +of love and shadows,4 +fort san felipe,2 +american express gold card dress of lizzy gardiner,4 +jovian,5 +kitashinagawa station,1 +radhi jaidi,1 +cordelia scaife may,2 +minor earth major sky,1 +bunty lawless stakes,1 +high capacity color barcode,3 +lyla lerrol,1 +crawford roberts,1 +collin balester,1 +ugo crousillat,1 +om prakash chautala,3 +izzy hoyland,1 +the poet,2 +daryl sabara,6 +aromatic acid,2 +reina sofia,1 +swierczek masovian voivodeship,1 +housing segregation in the united states,2 +karen maser,1 +scaptia beyonceae,2 +kitakyushu city,1 +htc desire 610,4 +dostoevsky,3 +portal victorian era,1 +bose–einstein correlations,3 +ralph hodgson,1 +racquet club,2 +walter camp man of the year,1 +australian movies,1 +k04he,1 +australia–india relations,2 +john william howard thompson,1 +pro cathedral,1 +paddyfield pipit,2 +book finance,1 +ford maverick,10 +slurve,4 +mnozil brass,2 +fiesta 9 1/8 inch square luncheon plate sunflower,1 +korsi,1 +draft 140th operations group,2 +camp,29 +series acceleration,1 +aljouf,1 +democratic party of new mexico,2 +united kingdom general election debates 2010,2 +madura strait,2 +back examination,1 +borgata,2 +il ritorno di tobia,3 +ovaphagous,1 +motörhead,9 +hellmaster,1 +richard keynes,1 +cryogenic treatment,3 +monte porzio,1 +transliteration of arabic,1 +anti catholic,2 +a very merry pooh year,2 +suffixes in hebrew,3 +barr body,16 +alaska constitution,1 +juan garrido,1 +yi lijun,1 +wawa inc,2 +endre kelemen,1 +l brands,18 +lr44,1 +coat of arms of the nagorno karabakh republic,1 +antonino fernandez,1 +salisbury roller girls,1 +zayat,2 +ian meadows,2 +semigalia,1 +khloe and lamar,2 +holding,1 +larchmont edgewater,1 +dynamic parcel distribution,6 +seaworld,30 +assistant secretary of war,1 +digital currency,14 +mazomanie wisconsin,1 +sujatha rangarajan,8 +street child,1 +anna sheehan,1 +violence jack,2 +santi solari,1 +template talk texas in the civil war,1 +colorss foundation,1 +faucaria,1 +alfred gardyne de chastelain,2 +tramp,1 +cannington ontario,2 +penguinone,1 +cardiac arrest,2 +summan grouper,1 +cyndis list,1 +cbs,2 +salminus brasiliensis,2 +kodiak bear,26 +cinemascore,9 +phragmidium,1 +city of vultures,1 +lawrence g romo,1 +chandni chowk to china,1 +scarp retreat,1 +rosses point,1 +carretera de cádiz,1 +chamunda,8 +battle of stalingrad,1 +who came first,2 +salome,5 +portuguese historical museum,3 +westfield sarasota square,1 +muehrckes nails,3 +kennebec north carolina,1 +american classical league,1 +how do you like them apples,1 +mark halperin,20 +circo,1 +turner classic movies,2 +australian rules football in sweden,1 +household silver,3 +frank baird,1 +escape from east berlin,2 +a village romeo and juliet,1 +wally nesbitt,6 +joseph renzulli,2 +spalding gray,1 +dangaria kandha,1 +pms asterisk,2 +openal,1 +romy haag,1 +mh message handling system,4 +pioneer 4,4 +hmcs stettler,1 +gangsta,10 +major third,4 +joan osbourn,1 +mount columbia,2 +active galactic nucleus,14 +robert clary,8 +eva pracht,1 +ion implantation,5 +rydell poepon,4 +baller blockin,2 +enfield chase railway station,1 +serge aurier,13 +florin vlaicu,1 +van diemens land,9 +krishnapur bagalkot,1 +oleksandr zinchenko,96 +collaborations,2 +hecla,2 +amber marshall,7 +inácio henrique de gouveia,1 +bronze age korea,1 +slc punk,5 +ryan jack,2 +clathrus ruber,6 +angel of death,4 +valentines park,1 +extra pyramidal,1 +kiami davael,1 +oleg i shuplyak,1 +nidum,2 +friendship of salem,2 +bèze,3 +arnold weinstock,1 +able,1 +s d ugamchand,1 +the omega glory,2 +ami james,3 +denmark at the 1968 summer olympics,1 +kill me again,1 +richmond town square,1 +guy domville,1 +jessica simpson,1 +kinship care,1 +brugge railway station,2 +unobtainium,16 +carl johan bernadotte,3 +acacia concinna,5 +epinomis,1 +interlachen country club,1 +compromise tariff,1 +fairchild jk,1 +dog trainer,1 +brian dabul,1 +cai yong,1 +jezebel,7 +augarten porcelain,1 +summerslam 1992,1 +ion andoni goikoetxea,2 +dominican church vienna,1 +iffhs worlds best club coach,2 +uruguayan presidential election 2009,2 +saving the queen,1 +un cadavre,1 +history of the jews in france,4 +wbyg,1 +charles de brosses,2 +human weapon,2 +haunted castle,3 +austin maestro,1 +search for extra terrestrial intelligence,1 +suwon,9 +cost per impression,1 +osney lock,1 +markus eriksson,1 +cultural depictions of tony blair,2 +erich kempka,3 +pornogrind,5 +chekhov,1 +marilinda garcia,2 +hard drive,1 +small arms,9 +exploration of north america,8 +international korfball federation,1 +photographic lens design,4 +k hari prasad,1 +lebanese forces,3 +greece at the 2004 summer olympics,1 +lets trim our hair in accordance with the socialist lifestyle,2 +battle of cassinga,5 +donald and the wheel,1 +vti transmission,1 +gille chlerig earl of mar,1 +heart of atlanta motel inc v united states,6 +oh yeah,3 +carol decker,5 +prajakta shukre,4 +profiling,17 +thukima,1 +the great waldo search,1 +nick vincent,2 +the decision of the appeals jury is final and can only be overruled by a decision of the executive committee 2e,1 +civilization board game,1 +erasmus+,1 +eden phillpotts,1 +unleash the beast,1 +varoujan hakhbandian,1 +fermats last theorem,1 +conan the indomitable,1 +vagrant records,1 +house of villehardouin,1 +zoneyesha ulatha,1 +ashur bel nisheshu,1 +ten wijngaerde,2 +lgi homes,1 +american nietzsche a history of an icon and his ideas,1 +european magpie,3 +pablo soto,1 +terminiello v chicago,1 +vladimir cosma,2 +battle of yunnan burma road,1 +ophirodexia,1 +thudar,1 +northern irish,2 +bohemond of tarente,1 +anita moorjani,5 +serra do gerês,1 +fort horsted,1 +metre gauge,2 +stage show,3 +common flexor sheath of hand,2 +conall corc,1 +array slicing,6 +schüfftan process,1 +anmol malik,3 +out cold,2 +antiknock,2 +moss force,1 +paul medhurst,1 +somonauk illinois,1 +george crum,11 +baby talk,6 +daniel mann,4 +vacuum flask,10 +prostitution in the republic of ireland,5 +butch jones,7 +feminism in ukraine,1 +st marys church kilmore county wexford,1 +sonny emory,1 +satsuma han,1 +elben,1 +the best of the rippingtons,3 +m3p,1 +boat sharing,1 +iisco,1 +hoftoren,1 +cannabis in the united kingdom,6 +template talk germany districts saxony anhalt,1 +jean baptiste dutrou bornier,1 +teylers museum,1 +simons problem,2 +gerardus huysmans,1 +pupillary distance,5 +jane lowe,1 +palais de justice brussels,1 +hillsdale free will baptist college,1 +raf wattisham,2 +parnataara,1 +jensen beach campus of the florida institute of technology,1 +scottish gypsy and traveller groups,3 +cliffs shaft mine museum,3 +roaring forties,4 +where in time is carmen sandiego?,2 +perfect field,1 +rob schamberger,1 +lcd soundsystem,10 +alan rathbone,26 +setup,1 +gliding over all,4 +dastur,1 +flensburger brauerei,3 +berkeley global campus at richmond bay,1 +kanakapura,1 +mineworkers union of namibia,1 +tokneneng,3 +mapuche textiles,3 +peranakan beaded slippers,1 +goodra,2 +kanab ut,1 +the gold act 1968,4 +grey langur,1 +procol harum,5 +chris alexander,1 +ft walton beach metropolitan area,3 +dimensionless quantity,16 +the science of mind,1 +alfons schone,1 +euparthenos nubilis,1 +batrachotoxin,5 +fabric live 22,1 +mchenry boatwright,1 +langney sports club,1 +akela jones,1 +lookout,2 +matsuo tsurayaba,2 +general jackson,3 +hair removal,14 +african party for the independence of cape verde,4 +replica trick,1 +bromfenac,2 +make someone happy,1 +sam pancake,1 +denys finch hatton,10 +latin rhythm albums,1 +main bronchus,1 +campidoglio,4 +cathaoirleach,1 +emress justina,1 +sulzbach hesse,1 +noncicatricial alopecia,1 +sylvan place,4 +stalag i c,1 +league of extraordinary gentlemen,1 +sergey korolyov,2 +serbian presidential election 1997,1 +barnes lake millers lake michigan,1 +christmas island health centre,1 +dayton ballet,2 +gilles fauconnier,1 +harald svergja,1 +joanna newsom discography,2 +astro xi yue hd,1 +code sharing,3 +dreamcast vmu,1 +armand emmanuel du plessis duc de richelieu,1 +ecole supérieure des arts du cirque,2 +gerry mulligan,12 +kaaka kaaka,1 +mexico at the 2012 summer olympics,4 +bar wizards,2 +christmas is almost here again,2 +sterling heights michigan,4 +gaultheria procumbens,3 +eben etzebeth,8 +viktorija Čmilytė,1 +los angeles county california,39 +family entertainment,2 +quantum well,9 +elton,1 +allan frewin jones,1 +daniela ruah,32 +gkd legend,1 +coffman–graham algorithm,1 +santa clara durango,1 +brian protheroe,3 +crawler transporter,10 +lakshman,3 +fes el bali,2 +mary a krupsak,1 +irish rugby football union,5 +neuropsychiatry,2 +josé pirela,1 +bonaire status referendum 2015,1 +it,2 +playhouse in the park,1 +alexander yakovlev,7 +old bear,1 +graph tool,2 +merseyside west,1 +romanian armies in the battle of stalingrad,1 +dark they were and golden eyed,1 +aidan obrien,8 +town and davis,1 +suum cuique,3 +german american day,2 +northampton county pennsylvania,3 +candidates of the south australian state election 2010,1 +venator marginatus,2 +k60an,1 +template talk campaignbox seven years war european,1 +maravi,1 +flaithbertach ua néill,1 +junction ohio,1 +dave walter,1 +london transport board,1 +tuyuka,1 +the moodys,3 +noel,3 +eugen richter,1 +cowanshannock township armstrong county pennsylvania,1 +pre columbian gold museum,1 +lac demosson,1 +lincosamides,9 +the vegas connection,1 +stephen e harris,1 +alkali feldspar,2 +brant hansen,1 +draft carnatic music stub,4 +the chemicals between us,1 +blood and bravery,1 +san diego flash,3 +covert channel,5 +ernest w adams,1 +hills brothers coffee,1 +cosmic background explorer,4 +international union of pure and applied physics,2 +vladimir kramnik,21 +hinterland,2 +tinker bell and the legend of the neverbeast,5 +ophisops jerdonii,1 +fine gold,1 +net explosive quantity,3 +miss colorado teen usa,3 +royal philharmonic orchestra discography,1 +elyazid maddour,1 +matthew kelly,2 +templating language,1 +japan campaign,2 +barack obama on mass surveillance,2 +thomas r donahue,1 +old right,4 +spencer kimball,1 +golden kela awards,1 +blinn college,3 +w k simms,1 +quinto romano,1 +richard mulrooney,1 +mr backup z64,1 +monetization of us in kind food aid,1 +alex chilton,2 +propaganda in the peoples republic of china,4 +jiří skalák,8 +m5 stuart tank,1 +template talk ap defensive players of the year,1 +crisis,2 +azuchi momoyama period,1 +care and maintenance,2 +a$ap mob,3 +near field communication,111 +hips hips hooray,1 +promotional cd,1 +andean hairy armadillo,1 +trigueros del valle,1 +elmwood illinois,1 +cantonment florida,2 +margo t oge,1 +national park service,36 +monongalia county ballpark,3 +bakemonogatari,6 +felicia michaels,1 +institute of oriental studies of the russian academy of sciences,2 +economy of eritrea,2 +vincenzo chiarenza,1 +microelectronics,4 +fresno state bulldogs mens basketball,1 +maotou,1 +blokely,1 +duplicati,3 +goud,2 +niki reiser,1 +edward leonard ellington,1 +jaswant singh of marwar,1 +biharsharif,1 +dynasty /trackback/,1 +machrihanish,4 +jay steinberg,1 +peter luger steak house,3 +palookaville,1 +ferrari grand prix results,2 +bankruptcy discharge,2 +mike mccue,2 +nuestra belleza méxico 2013,2 +alex neal bullen,1 +gus macdonald baron macdonald of tradeston,2 +florida circuit court,1 +haarp,2 +v pudur block,1 +grocer,1 +shmuel hanavi,1 +isaqueena falls,2 +jean moulin university,1 +final fantasy collection,1 +template talk american frontier,1 +chex quest,4 +muslim students association,2 +marco pique,1 +jinja safari,1 +the collection,9 +urban districts of germany,5 +rajiv chilaka,1 +zion,2 +vf 32,1 +united states commission on civil rights,2 +zazam,1 +barnettas,4 +rebecca blasband,1 +lincoln village,1 +film soundtracks,1 +angus t jones,77 +snuppy,3 +w/indexphp,30 +file talk american world war ii senior military officials 1945jpeg,1 +worship leader,1 +ein qiniya,1 +buxton maine,1 +matt dewitt,1 +béla bollobás,3 +earlysville union church,1 +bae/mcdonnell douglas harrier ii gr9,1 +californian condor,2 +progressive enhancement,15 +its not my time,4 +ecw on tnn,2 +ihop,36 +aeronautical chart,1 +clique width,1 +fuengirola,8 +archicebus achilles,2 +comparison of alcopops,1 +carla anderson hills,1 +roanoke county virginia,2 +jaílson alves dos santos,1 +rameses revenge,1 +kaycee stroh,5 +les experts,1 +niels skousen,1 +apollo hoax theories,1 +mercedes w204,2 +enhanced mitigation experience toolkit,15 +bert barnes,1 +serializability,6 +ten plagues of egypt,1 +joe l brown,1 +category talk high importance chicago bears articles,1 +stephen caffrey,3 +european border surveillance system,2 +achytonix,1 +m2 machine gun,1 +gurieli,1 +kunefe,1 +m33 helmet,3 +little carmine,1 +smush,3 +josé horacio gómez,1 +product recall,1 +egger,1 +wisconsin highway 55,1 +harbledown,1 +low copy repeats,1 +curt gentry,1 +united colors of benetton,1 +adiabatic shear band,2 +pea galaxy,1 +where are you now,1 +dils,1 +surprise s1,1 +senate oceans caucus,2 +windsor new hampshire,1 +a hawk and a hacksaw,1 +i love it loud,2 +milbcom,1 +old world vulture,7 +camara v municipal court of city and county of san francisco,1 +ski dubai,1 +st cyprians school,2 +aibo,1 +ticker symbol,2 +hendrik houthakker,1 +shivering,5 +jacob arminius,1 +mowming,1 +panjiva,2 +namco libble rabble,5 +rudolph bing,1 +sindhi cap,2 +logician,1 +ford xa falcon,2 +the sunny side up show,1 +helen adams,2 +kharchin,1 +brittany maynard,13 +kim kyu jong,1 +messier 103,3 +leon boiler,1 +the rapeman,1 +twa flight 3,4 +leading ladies,1 +delta octantis,2 +qatari nationality law,1 +lionel cripps,1 +josé daniel carreño,1 +crypsotidia longicosta,1 +polish falcons,1 +highlands north gauteng,1 +the florida channel,1 +oreste barale,1 +ghazi of iraq,2 +charles grandison finney,4 +ahmet ali,1 +abbeytown,1 +caribou,3 +big two,2 +alien,14 +aslantaş dam,3 +theme of the traitor and the hero,1 +vladimir solovyov,1 +laguna ojo de liebre,1 +clive barton,1 +ebrahim daoud nonoo,1 +richard goodwin keats,2 +back to the who tour 51,1 +entertainmentwise,1 +ja preston,1 +john astin,19 +strict function,1 +cam ranh international airport,2 +gary pearson,1 +sven väth,8 +toad,6 +johnny pace,1 +hunt stockwell,1 +rolando schiavi,1 +claudia grassl,1 +oxford nova scotia,1 +maryland sheep and wool festival,1 +conquest of bread,1 +erevan,1 +comparison of islamic and jewish dietary laws,11 +sheila burnford,1 +estevan payan,1 +ocean butterflies international,7 +the royal winnipeg rifles,1 +green goblin in other media,2 +video gaming in japan,8 +church of the guanche people,4 +gustav hartlaub,2 +ian mcgeechan,4 +hammer and sickle,17 +konkiep river,1 +ceri richards,1 +decentralized,2 +depth psychology,3 +centennial parkway,1 +yugoslav monitor vardar,1 +battle of bobbili,2 +magnus iii of sweden,1 +england c national football team,2 +thuraakunu,1 +bab el ehr,1 +koi,1 +cully wilson,1 +money laundering,1 +stirling western australia,1 +jennifer dinoia,1 +eureka street,1 +message / call my name,1 +make in maharashtra,4 +huckleberry creek patrol cabin,1 +almost famous,5 +truck nuts,4 +vocus communications,1 +gikwik,1 +battle of bataan,4 +confluence pennsylvania,2 +islander 23,1 +mv skorpios ii,1 +single wire earth return,1 +politics of odisha,1 +crédit du nord,3 +piper methysticum,2 +coble,2 +kathleen a mattea,1 +coachella valley music and arts festival,50 +tooniverse,1 +spofforth castle,1 +arabian knight,2 +two airlines policy,1 +hinduja group,17 +swagg alabama,1 +portuguese profanity,1 +loomis gang,2 +nina veselova,2 +aegyrcitherium,1 +bees in paradise,1 +béládys anomaly,3 +badalte rishtey,1 +first bank fc,1 +cystoseira,1 +red book of endangered languages,1 +rose,6 +terry mcgurrin,3 +jason hawke,1 +peter chernin,1 +tu 204,1 +the man who walked alone,1 +tool grade steel,1 +wrist spin,1 +one step forward two steps back,1 +theodor boveri,1 +heunginjimun,1 +fama–french three factor model,34 +billy whitehurst,1 +rip it up,4 +red lorry yellow lorry,4 +nao tōyama,8 +general macarthur,1 +rabi oscillation,2 +devín,1 +olympus e 420,1 +hydra entertainment,1 +chris cheney,3 +rio all suite hotel and casino,3 +the death gate cycle,2 +fatima,1 +kamomioya shrine,1 +five nights at freddys 3,14 +the broom of the system,3 +robert blincoe,1 +history of wells fargo,9 +pinocytosis,4 +leaf phoenix,1 +wxmw,2 +tommy henriksen,13 +geri halliwell discography,2 +blade runneri have seen things you would not believe,1 +madhwa brahmins,1 +i/o ventures,1 +edorisi master ekhosuehi,2 +junior orange bowl,1 +khit,2 +sue jones,1 +immortalized,35 +city building series,4 +quran translation,1 +united states consulate,1 +dose response relationship,1 +caitriona,1 +colocolo,21 +medea class destroyer,1 +vaastav,1 +etc1,1 +john altoon,2 +thylacine,113 +cycling at the 1924 summer olympics,1 +margaret nagle,1 +superpower,57 +gülşen,1 +anthems to the welkin at dusk,4 +yerevan united fc,1 +the family fang,14 +domain,4 +high speed rail in india,14 +trifolium pratense,7 +florida mountains,2 +national city corp,5 +length of us participation in major wars,2 +acacia acanthoclada,1 +offas dyke path,2 +enduro,7 +howard center,1 +littlebits,4 +plácido domingo jr,1 +hookdale illinois,1 +the love language,1 +cupids arrows,1 +dc talk,7 +maesopsis eminii,1 +here comes goodbye,1 +freddie foreman,5 +marvel comics publishers,1 +consolidated city–county,5 +countess marianne bernadotte of wisborg,1 +los angeles baptist high school,1 +maglalatik,1 +deo,2 +meilichiu,1 +wade coleman,1 +monster soul,2 +julion alvarez,2 +platinum 166,1 +shark week,12 +hossbach memorandum,4 +jack c massey,3 +ardore,1 +philosopher king,5 +dynamic random access memory,5 +bronze age in southeastern europe,1 +tamil films of 2012,1 +nathalie cely,1 +italian capital,1 +optic tract,3 +shakti kumar,1 +who killed bruce lee,1 +parlement of brittany,3 +san juan national historic site,2 +livewell,2 +template talk om,1 +al bell,2 +pzl w 3 sokół,8 +durrës rail station,3 +david stubbs,1 +pharmacon,3 +railfan,7 +comics by country,2 +cullen baker,1 +maximum subarray problem,19 +outlaws and angels,1 +paradise falls,2 +mathias pogba,28 +donella meadows,4 +john leconte,2 +swaziland national football team,7 +gabriele detti,2 +if ever youre in my arms again,1 +christian basso,1 +helen shapiro,7 +taisha abelar,1 +fluid dynamics,1 +ernest wilberforce,1 +kocaeli university,2 +british m class submarine,1 +modern woodmen of america,1 +las posadas,3 +federal budget of germany,2 +liberation front of chad,1 +sandomierz,5 +ap italian language and culture,1 +manuel gonzález,1 +georgian military road,2 +clear creek county colorado,1 +matt clark,2 +test tube,18 +ak 47,1 +diège,1 +london school of economics+,1 +michael york,14 +half eagle,6 +strike force,1 +type 054 frigate,2 +sino indian relations,7 +fern,3 +louvencourt,1 +ghb receptor,2 +chondrolaryngoplasty,2 +andrew lewer,1 +ross king,1 +colpix records,1 +october 28,1 +tatsunori hara,1 +rossana lópez león,1 +haskell texas,3 +tower subway,2 +waspstrumental,1 +template talk nba anniversary teams,1 +george leo leech,1 +still nothing moves you,1 +blood cancer,3 +buffy lynne williams,1 +dpgc u know what im throwin up,1 +daniel nadler,1 +khalifa sankaré,2 +homo genus,1 +garðar thór cortes,3 +veyyil,1 +matt dodge,1 +hipponix subrufus,1 +anostraca,1 +hartshill park,1 +purple acid phosphatases,1 +austromyrtus dulcis,1 +shamirpet lake,1 +favila of asturias,2 +acute gastroenteritis,1 +dalton cache pleasant camp border crossing,1 +urobilinogen,13 +ss kawartha park,1 +professional chess association,1 +species extinction,1 +gapa hele bi sata,1 +phyllis lyon and del martin,1 +uk–us extradition treaty of 2003,1 +a woman killed with kindness,1 +how bizarre,1 +norm augustine,1 +geil,1 +volleyball at the 2015 southeast asian games,2 +jim ottaviani,1 +chekmagushevskiy district,1 +information search process,2 +queer,63 +william pidgeon,1 +amelia adamo,1 +nato ouvrage "g",1 +tamsin beaumont,1 +economy of syria,13 +douglas dc 8 20,1 +tama and friends,4 +pringles,22 +kannada grammar,7 +lotoja,1 +peony,1 +bmmi,1 +eurovision song contest 1992,11 +cerro blanco metro station,1 +sherlock the riddle of the crown jewels,4 +dorsa cato,1 +nkg2d,8 +specific heat,6 +nokia 6310i,2 +tergum,2 +bahai temple,1 +dal segno,5 +leigh chapman,2 +tupolev tu 144,60 +flight of ideas,1 +rita montaner,1 +vivien a schmidt,1 +battle of the treasury islands,2 +three kinds of evil destination,1 +richlite,1 +medinilla,2 +timeline of aids,1 +colin renfrew baron renfrew of kaimsthorn,2 +hélène rollès,1 +pedro winter,1 +sabine free state,1 +brzeg,1 +palisades park,1 +gas gangrene,11 +dotyk,2 +daniela kix,1 +canna,16 +property list,9 +john hamburg,1 +dunk island,5 +albreda,1 +scammed yankees,1 +wireball,3 +junior 4,1 +absolutely anything,15 +linux operating system,1 +solsbury hill,15 +notopholia,1 +scottish heraldry,2 +template talk paper data storage media,1 +category talk religion in ancient sparta,1 +category talk cancer deaths in puerto rico,1 +mid michigan community college,2 +tvb anniversary awards,1 +frederick taylor gates,1 +omoiyari yosan,3 +journal of the physical society of japan,1 +kings in the corner,2 +nungua,1 +amerika,4 +pacific marine environmental laboratory,1 +the thought exchange,1 +italian bee,5 +roma in spain,1 +sirinart,1 +crandon wisconsin,1 +shubnikov–de haas effect,6 +portrait of maria portinari,4 +colin mcmanus,1 +universal personal telecommunications,1 +royal docks,4 +brecon and radnorshire,3 +eilema caledonica,1 +chalon sur saône,8 +toyota grand hiace,1 +sophorose,1 +semirefined 2bwax,1 +mechanics institute chess club,1 +the culture high,2 +dont wake me up,1 +transcaucasian mole vole,1 +harry zvi tabor,1 +vhs assault rifle,1 +playing possum,2 +omar minaya,2 +private university,1 +yuki togashi,3 +ski free,2 +say no more,1 +diving at the 1999 summer universiade,1 +armando sosa peña,1 +timur tekkal,1 +jura elektroapparate,1 +pornographic magazine,1 +tukur yusuf buratai,1 +keep on moving,1 +laboulbeniomycetes,1 +chiropractor solve problems,1 +mark s allen,3 +committees of the european parliament,4 +blondie,7 +veblungsnes,1 +bank vault,10 +smiling irish eyes,1 +robert kalina,2 +polarization ellipse,2 +huntingdon priory,1 +energy in the united kingdom,34 +hamble,1 +raja sikander zaman,1 +perigea hippia,1 +college of liberal arts and sciences,1 +bootblock,1 +nato reporting names,2 +the serpentwar saga,1 +reformed churches in the netherlands,1 +collaborative document review,4 +combat mission beyond overlord,3 +vlra,2 +pat st john,1 +oceanid,5 +itapetinga,1 +insane championship wrestling,9 +nathaniel gorham,1 +estadio metropolitano de fútbol de lara,2 +william of saint amour,2 +new york drama critics circle award,1 +alliant rq 6 outrider,2 +ilsan,1 +top model po russki,1 +woolens,1 +rutledge minnesota,1 +joigny coach crash,2 +zhou enlai the last perfect revolutionary,1 +the theoretical minimum,1 +arrow security,1 +john shelton wilder,2 +jasdf,2 +katie may,2 +american jewish military history project,1 +business professionals of america,1 +questioned document examination,5 +motorola a760,1 +american steel & wire,1 +louis armstrong at the crescendo vol 1,1 +edward vernon,3 +maria taipaleenmäki,1 +margical history tour,2 +jar jar,1 +australian oxford dictionary,2 +revenue service,2 +odoardo farnese hereditary prince of parma,1 +weekend in new england,1 +laurence harbor new jersey,2 +aramark tower,1 +stealers wheel,1 +cephalon,1 +dawnguard,1 +saintsbury,2 +saint fuscien,1 +ryoko kuninaka,1 +farm to market road 1535,1 +alan kennedy,2 +esteban casagolda,1 +shin angyo onshi,1 +william gowland,1 +eastern religions,6 +kenny lala,1 +alphonso davies,1 +tadamasa hayashi,1 +meet the parents,2 +calvinist church,1 +ristorante paradiso,1 +jose joaquim champalimaud,1 +olis,1 +mill hill school,2 +lockroy,1 +battle of princeton,10 +cent,8 +brough superior ss80,1 +ras al khaima club,3 +washington international university,3 +bradley kasal,2 +miguel Ángel varvello,1 +oxygen permeability,1 +femoral circumflex artery,1 +golden sun dark dawn,4 +pusarla sindhu,1 +toyota winglet,1 +wind profiler,1 +montefiore medical center,2 +template talk guitar hero series,3 +little leaf linden,1 +ramana,4 +islam in the czech republic,2 +manuel vitorino,1 +joseph radetzky von radetz,3 +francois damiens,1 +parasite fighter,1 +friday night at st andrews,3 +hurbazum,1 +haidhausen,1 +petabox,2 +salmonella enteritidis,2 +matthew r denver,1 +de la salle,1 +anti terrorism act 2015,6 +brugsen,1 +mountain times,1 +columbia basin project,1 +common wallaroo,2 +clepsis brunneograpta,1 +red hot + dance,1 +mao fumei,1 +dark shrew,1 +coach,8 +come saturday morning,1 +aanmai thavarael,1 +hellenia,1 +donate life america,2 +plot of beauty and the beast toronto musical,1 +births in 1243,3 +main page/wiki/portal technology,8 +cambridgeshire archives and local studies,1 +big pines california,1 +pegasus in popular culture,4 +baron glendonbrook,1 +your face sounds familiar,5 +boom tube,2 +richard gough,8 +the new beginning in niigata,3 +american academy of health physics,1 +plain,9 +tushino airfield,1 +king george v coronation medal,1 +geologic overpressure,1 +seille,1 +calorimeter,25 +french civil service,1 +david l paterson,1 +chinese gunboat chung shan,2 +rhizobium inoculants,1 +wizard,4 +baghestan,1 +paustian house,2 +ellen pompeo,55 +damien williams,1 +tomoe tamiyasu,1 +acute epithelial keratitis,1 +casey abrams,8 +mendozite,1 +kantian ethics,2 +mcclure syndicate,1 +tokyo metro,6 +cuisine of guinea bissau,1 +mossberg 500,18 +mollie gillen,1 +above and beyond party,1 +joey carbone,1 +faulkner state community college,1 +tetsuya ishikawa,1 +electric flag,3 +meet the feebles,2 +kplm,1 +when we were twenty one,1 +horus bird,2 +youth in revolt,8 +spongebob squarepants revenge of the flying dutchman,3 +ehow,5 +nikos xydakis,2 +ziprasidone,19 +ulsan airport,1 +flechtingen,1 +dave christian,3 +delaware national guard,1 +skaria thomas,1 +iraca,1 +kkhi,2 +swimming at the 2015 world aquatics championships – mens 1500 metre freestyle,2 +crossing lines,37 +john du cane,1 +i8,1 +bauer pottery,1 +affinity sutton,4 +lotus 119,1 +uss arleigh burke,1 +palmar interossei,2 +nofx discography,4 +bwia west indies airways,3 +gopala ii,1 +north fork correctional facility,1 +szeged 2011,1 +milligram per cent,2 +halas and batchelor,1 +what the day owes the night,1 +sighișoara medieval festival,5 +scarning railway station,1 +cambridge hospital,1 +amnesia labyrinth,2 +cokie roberts,7 +savings identity,3 +pravia,1 +mcgrath,4 +pakistan boy scouts association,1 +dan carpenter,2 +marikina–infanta highway,2 +genetic analysis,2 +template talk ohio state university,1 +thomas chamberlain,4 +moe book,1 +coyote waits,1 +black protestant,1 +neetu singh,19 +mahmoud sarsak,1 +casa loma,28 +bedivere,8 +boundary park,2 +danger danger,14 +jennifer coolidge,49 +pop ya collar,1 +collaboration with the axis powers during world war ii,10 +greenskeepers,1 +the dukes children,1 +alaska off road warriors,1 +twenty five satang coin,1 +template talk private equity investors,2 +american red cross,24 +jason shepherd,1 +georgetown college,2 +ocean countess,1 +ammonium magnesium phosphate,1 +community supported agriculture,5 +philosophy of suicide,4 +yard ramp,2 +captain germany,1 +bob klapisch,1 +i will never let you down,2 +february 11,6 +ron dennis,13 +rancid,16 +the mall blackburn,1 +south high school,6 +charles allen culberson,1 +organizational behavior,66 +automatic route selection,1 +uss the sullivans,9 +yo no creo en los hombres,1 +janet,1 +serena armstrong jones viscountess linley,3 +louisiana–lafayette ragin cajuns mens basketball,1 +flower films,1 +michelle ellsworth,1 +norbertine rite,2 +spanish mump,1 +shah jahan,67 +fraser coast region,1 +matt cornwell,1 +nra,1 +crested butte mountain resort,1 +college football playoff national championship,2 +craig heaney,4 +devil weed,1 +satsuki sho,1 +jordaan brown,1 +little annie,4 +thiha htet aung,1 +the disreputable history of frankie landau banks,1 +mickey lewis,1 +eldar nizamutdinov,1 +m1825 forage cap,1 +antonina makarova,1 +mopani district municipality,2 +al jahra sc,1 +chaim topol,4 +tum saath ho jab apne,1 +piff the magic dragon,7 +imagining argentina,1 +ni 62,1 +phys rev lett,1 +the peoples political party,1 +casoto,1 +popular movement of the revolution,4 +huntingtown maryland,1 +la bohème,33 +khirbat al jawfa,1 +lycksele zoo,1 +deveti krug,2 +cuba at the 2000 summer olympics,2 +rose wilson,7 +sammy lee,2 +dave sheridan,10 +universal records,2 +antiquities trade,3 +shoveller,1 +tapered integration,1 +parker pen company,4 +mushahid hussain syed,1 +nynehead,1 +counter reformation,2 +nhl on nbc,11 +ronny rosenthal,2 +arsenie todiraş,3 +lobster random,1 +halliburton,37 +gordon county georgia,1 +belle isle florida,3 +molly stanton,3 +green crombec,1 +geodesist,2 +abd al rahman al sufi,4 +demography of japan,26 +live xxx tv,5 +naihanchi,1 +cofinite,1 +msnbot,5 +clausard,1 +mimidae,1 +wind direction,15 +irrational winding of a torus,1 +tursiops truncatus,1 +trustee,1 +lumacaftor/ivacaftor,2 +balancing lake,2 +shoe trees,1 +cycling at the 1928 summer olympics – mens team pursuit,1 +calponia harrisonfordi,1 +hindu rate of growth,1 +dee gordon,7 +passion white flag,2 +frog skin,1 +rudolf eucken,2 +bayantal govisümber,1 +christopher a iannella,1 +robert myers,1 +james simons,1 +meng xuenong,1 +abayomi olonisakin,1 +milton wynants,1 +cincinnatus powell,1 +atomic bomb band,1 +hopfield network,12 +jet pocket top must,1 +the state of the world,1 +welf i duke of bavaria,2 +american civil liberties union v national security agency,3 +elizabeth fedde,1 +librarything,2 +kim fletcher,1 +tracy island,2 +praise song for the day,1 +superstar,7 +ewen spencer,1 +back striped weasel,1 +cs concordia chiajna,1 +bruce curry,1 +malificent,1 +dr b r ambedkar university,2 +river plate,1 +desha county arkansas,1 +harare declaration,2 +patrick dehornoy,1 +paul alan cox,2 +auckland mounted rifles regiment,1 +mikoyan gurevich dis,3 +corn exchange manchester,2 +sharpshooter,1 +the new york times manga best sellers of 2013,1 +max perutz,2 +andrei makolov,1 +inazuma eleven saikyō gundan Ōga shūrai,2 +tatra 816,1 +ashwin sanghi,8 +pipestone township michigan,1 +craig shoemaker,1 +david bateson,1 +lew lehr,1 +crewe to manchester line,2 +samurai champloo,36 +tali ploskov,2 +janet sobel,3 +kabe station,1 +rippon,1 +alexander iii equestrian,1 +louban,2 +the twelfth night,1 +delaware state forest,1 +the amazing race china 3,1 +brillouins theorem,1 +extreme north,3 +super frelon,1 +george watsons,1 +mungo park,1 +workin together,3 +boy,12 +brownsville toros,1 +kim lim,1 +futsal,63 +motoring taxation in the united kingdom,1 +accelerator physics codes,1 +arytenoid cartilage,3 +the price of beauty,3 +life on the murder scene,2 +hydrophysa psyllalis,1 +jürgen brandt,2 +economic history association,2 +the sandwich girl,1 +heber macmahon,1 +volume 1 sound magic,2 +san francisco–oakland–hayward ca metropolitan statistical area,9 +harriet green,7 +tarnawa kolonia,1 +eur1 movement certificate,20 +anna nolan,2 +gulf of gökova,1 +havertown,2 +orlando scandrick,4 +doug owston correctional centre,1 +asterionella,4 +espostoa,1 +ranked voting system,10 +commercial law,39 +kirk,1 +mongolian cuisine,8 +turfanosuchus,1 +arthur anderson,4 +sven olof lindholm,1 +batherton,1 +dimetrodon,1 +pianos become the teeth,1 +united kingdom in the eurovision song contest 1976,1 +medieval,11 +it bites,1 +ion television,8 +seaboard system railroad,3 +sayan mountains,3 +musaffah,1 +charles de foucauld,3 +urgh a music war,1 +translit,1 +american revolutionary war/article from the 1911 encyclopedia part 1,1 +uss mauna kea,1 +powder burn,1 +bald faced hornet,9 +producer of the year,1 +the most wanted man,1 +clear history,8 +mikael lilius,1 +class invariant,4 +forever michael,3 +goofing off,3 +tower viewer,3 +claudiu marin,1 +nicolas cage,1 +waol,2 +s10 nbc respirator,2 +education outreach,1 +gyeongsan,2 +template talk saints2008draftpicks,1 +botaurus,1 +francis harper,1 +mauritanian general election 1971,1 +kirsty roper,2 +non steroidal anti inflammatory drug,17 +nearchus of elea,2 +resistance to antiviral drugs,1 +raghavendra rajkumar,5 +template talk cc sa/sandbox,1 +washington gubernatorial election 2012,2 +paul lovens,1 +express freighters australia,2 +bunny bleu,2 +osaka prefecture,2 +federal reserve bank of boston,4 +hacı ahmet,1 +underground chapter 1,10 +filippo simeoni,2 +the wonderful wizard of oz,3 +sailing away,1 +avelino gomez memorial award,1 +badger,65 +hongkou football stadium,3 +benjamin f cheatham,2 +fair isaac,2 +kwab,1 +al hank aaron award,3 +gender in dutch grammar,1 +idiom neutral,2 +da lata,1 +tuu languages,1 +derivations are used,1 +clete patterson,1 +danish folklore,4 +android app //orgwikipedia/http/enmwikipediaorg/wiki/westfield academy,1 +toto,8 +ea,1 +victory bond tour,1 +credai,2 +hérin,1 +st james louisiana,1 +necrolestes,2 +cable knit,1 +saunderstown,1 +us route 52 in ohio,1 +sailors rest tennessee,1 +adlai stevenson i,6 +miscibility,13 +help footnotes,13 +murrell belanger,1 +new holland pennsylvania,5 +haldanodon,1 +feminine psychology,2 +riot city wrestling,1 +mobile content management system,2 +zinio,1 +central differencing scheme,2 +enoch,2 +usp florence admax,1 +maester aemon,7 +norman "lechero" st john,1 +ice racing,1 +tiger cub economies,6 +klaipėda region,12 +wu qian,8 +malayalam films of 1987,1 +estadio nuevo la victoria,1 +nanotoxicology,2 +hot revolver,1 +nives ivankovic,1 +glen edward rogers,5 +epicene,3 +eochaid ailtlethan,1 +judiciary of finland,1 +en jersey,1 +statc,1 +atta kim,1 +mizi research,2 +acs applied materials & interfaces,1 +thank god youre here,9 +loneliness,8 +h e b plus,2 +corella bohol,1 +money in the bank,59 +golden circle air t bird,1 +flash forward,1 +category talk philippine television series by network,1 +dfmda,1 +the road to wellville,8 +ernst tüscher,1 +commission,14 +abdul rahman bin faisal,6 +oversea chinese banking corporation,7 +ray malavasi,1 +al qadisiyah fc,4 +anisfield wolf book award,1 +jacques van rees,1 +jakki tha motamouth,1 +scoop,1 +piti,2 +carlos reyes,1 +v o chidambaram pillai,6 +diamonds sparkle,1 +the great transformation,5 +cardston alberta temple,1 +la vendetta,1 +miyota nagano,1 +national shrine of st elizabeth ann seton,2 +chaotic,1 +breastfeeding and hiv,1 +friedemann schulz von thun,1 +mukhammas,2 +fishbowl worldwide media,1 +mohamed amin,3 +john densmore,10 +suryadevara nayaks,1 +metal gear solid peace walker,12 +ché café,2 +old growth,1 +lake view cemetery,1 +konigsberg class cruiser,1 +courts of law,1 +nova scotia peninsula,3 +jairam ramesh,4 +portal kerala/introduction,1 +edinburgh 50 000 – the final push,1 +ludachristmas,3 +motion blur,1 +deliberative process privilege,2 +bubblegram,1 +simon breach grenade,2 +tess henley,1 +gojinjo daiko,1 +common support aircraft,2 +zelda rubinstein,9 +yolanda kakabadse,1 +american studio woodturning movement,1 +richard carpenter,67 +vehicle door,3 +transmission system operator,9 +christa campbell,9 +marolles en brie,1 +korsholma castle,1 +murder of annie le,3 +kims,1 +zionist union,8 +portal current events/june 2004,2 +marination,8 +cap haïtien international airport,2 +fujima kansai,1 +vampire weekend discography,3 +moncton coliseum,2 +wing chair,1 +el laco,2 +castle fraser,1 +template talk greek political parties,1 +society finch,1 +chief executive officer,4 +battle of bloody run,3 +coat of arms of tunisia,2 +nishi kawaguchi station,1 +colonoscopy,30 +vic tayback,5 +lonnie mack discography,3 +yusuf salman yusuf,2 +marco simone,4 +saint just,1 +elizabeth taylor filmography,6 +haglöfs,2 +yunis al astal,1 +daymond john,36 +bedd y cawr hillfort,1 +durjoy datta,1 +wealtheow,1 +aaron mceneff,1 +culture in berlin,1 +temple of saturn,6 +nermin zolotić,1 +the darwin awards,1 +patricio pérez,1 +chris levine,1 +misanthropic,1 +dragster,2 +eldar,19 +chrzanowo gmina szelków,1 +zimmerberg base tunnel,6 +jakob schaffner,1 +california gubernatorial recall election 2003,1 +tommy moe,1 +bikrami calendar,1 +mama said,11 +hellenic armed forces,8 +candy box,3 +monstervision,3 +kachin independent army,1 +pro choice,1 +tshiluba language,1 +trucial states,9 +collana,1 +best music video short form,1 +pokémon +giratina+and+the+sky+warrior,1 +etteldorf,1 +academic grading in chile,2 +land and liberty,3 +australian bureau of meteorology,1 +cheoin gu,1 +william henry green,1 +ewsd,2 +gate of hell,1 +sioux falls regional airport,3 +nevelj zsenit,1 +bevo lebourveau,1 +ranjana ami ar asbona,1 +shaun fleming,1 +jean antoine siméon fort,1 +sports book,1 +vedran smailović,3 +simple harmonic motion,29 +wikipedia talk wikiproject film/archive 16,1 +princess jasmine,13 +great bustard,5 +allred unit,1 +cheng san,1 +mini paceman,1 +flavoprotein,2 +storage wars canada,3 +university rowing,2 +category talk wikiproject saskatchewan communities,1 +the washington sun,1 +rotary dial,6 +hailar district,1 +assistant secretary of the air force,2 +the décoration for the yellow house,5 +chris mclennan,1 +the cincinnati kid,4 +education in the republic of ireland,15 +steve brodie,2 +country club of detroit,1 +wazner,1 +portal spain,4 +senna,3 +william j bernd house,1 +balaji baji rao,8 +worth dying for,1 +cool ruler,1 +turn your lights down low,2 +mavroudis bougaidis,1 +national registry emergency medical technician,1 +james young,8 +eyewire,1 +dark matters twisted but true/,1 +josé pascual monzo,1 +german election 1928,2 +linton vassell,1 +convention on the participation of foreigners in public life at local level,1 +thorium fuel cycle,5 +honeybaby honeybaby,1 +golestan palace,3 +lombok international airport,11 +mainichi daily news,1 +k&p,1 +liberal network for latin america,1 +cádiz memorial,1 +grupo corripio,1 +elie and earlsferry,1 +isidore geoffroy saint hilaire,1 +al salmiya sc,2 +piano sonata hob xvi/33,1 +e f bleiler,1 +national register of historic places listings in york county virginia,3 +gupta empire,2 +german immigration to the united states,1 +through gates of splendor,2 +iap,1 +love takes wing,1 +tours de merle,1 +aleksey zelensky,1 +paul almond,2 +boston cambridge quincy ma nh metropolitan statistical area,1 +komiks presents dragonna,1 +princess victoire of france,1 +alan pownall,3 +tilak nagar,2 +lg life sciences co ltd,8 +before their eyes,1 +labor right,5 +michiko to hatchin,1 +susan p graber,1 +xii,1 +hanswulf,1 +symbol rate,17 +myo18b,2 +rowing at the 2010 asian games – mens coxed eight,1 +caspar weinberger jr,2 +bettle juice,1 +battle of the morannon,7 +darlington county south carolina,1 +mayfield pennsylvania,1 +ruwerrupt de mad,1 +luthfi assyaukanie,1 +fiat panda,30 +wickiup reservoir,1 +tanabe–sugano diagram,6 +alexander sacher masoch prize,1 +intracellular transport,1 +church of the val de grâce,1 +jebel ad dair,1 +rosalind e krauss,6 +cross origin resource sharing,97 +readiness to sacrifice,1 +creel terrazas family,1 +phase portrait,9 +subepithelial connective tissue graft,1 +lake malawi,18 +phillips & drew,1 +ernst vom rath,2 +infinitus,1 +geneva convention for the amelioration of the condition of the wounded and sick in armies in the field,2 +world heritage,1 +dole whip,8 +leveling effect,1 +bioship,3 +vanilloids,2 +superionic conductor,1 +basil bernstein,7 +armin b cremers,2 +szlichtyngowa,1 +beixinqiao station,1 +united states presidential election in utah 1980,1 +watson v united states,3 +willie mcgill,1 +melle belgium,1 +al majmaah,1 +mesolimbic dopamine pathway,1 +six flags new england,5 +acp,2 +geostrategy,2 +original folk blues,1 +wentworth military academy,1 +bromodichloromethane,3 +doublet,4 +tawfiq al rabiah,1 +sergej jakirović,1 +mako surgical corp,3 +empire of lies,1 +old southwest,1 +bay of arguin,1 +bringing up buddy,1 +mustapha hadji,7 +raymond kopa,7 +evil horde,1 +kettering england,1 +extravaganza,1 +christian labour party,2 +joice mujuru,6 +v,15 +le père,4 +my fathers dragon,2 +cumulus cloud,32 +fantasy on themes from mozarts figaro and don giovanni,1 +postpone indefinitely,1 +extreme point,1 +iraq–israel relations,1 +henry le scrope 3rd baron scrope of masham,1 +rating beer,1 +claude alvin villee jr,2 +clackamas town center,2 +roope latvala,4 +richard bethell 1st baron westbury,1 +ryan gosling,1 +yelina salas,1 +amicus,1 +cecilia bowes lyon countess of strathmore and kinghorne,6 +programming style,9 +now and then,9 +somethingawful,1 +nuka hiva campaign,1 +bostongurka,2 +jorge luis ochoa vázquez,1 +philip burton,1 +rainbow fish,7 +road kill,5 +christiane frenette,2 +as if,1 +paul ricard,1 +roberto dañino,1 +shoyu,1 +jakarta,96 +dean keith simonton,1 +mastocytosis,19 +hiroko yakushimaru,3 +problem of other minds,2 +jaunutis,1 +tfp deficiency,1 +access atlantech edutainment,1 +kristian thulesen dahl,1 +william wei,1 +andy san dimas,10 +kempten/allgäu,1 +augustus caesar,9 +conrad janis,1 +tugaya lanao del sur,1 +second generation antipsychotics,1 +anema e core,2 +sucking the 70s,1 +the czars,2 +vakulabharanam,1 +f double sharp,3 +prymnesin,1 +dick bavetta,2 +billy jones,3 +columbine,4 +file talk joseph bidenjpg,1 +mandelbrot set,79 +constant elasticity of variance model,2 +morris method,1 +al shamal stadium,5 +hes alright,1 +madurai massacre,1 +philip kwon,2 +christadelphians,7 +this man is dangerous,2 +kiowa creek community church,1 +pier paolo vergerio,1 +order of the most holy annunciation,2 +john plender,1 +vallée de joux,2 +graysby,1 +ludwig minkus,3 +potato aphid,1 +bánh bột chiên,1 +wilhelmstraße,1 +fee waybill,1 +designed to sell,1 +ironfall invasion,2 +lieutenant governor of the isle of man,1 +third reading,2 +eleanor roosevelt high school,1 +su zhe,1 +heat conductivity,1 +si satchanalai national park,1 +etale space,1 +faq,24 +low carbohydrate diet,1 +differentiation of integrals,1 +karl fogel,2 +tom chapman,3 +james gamble rogers,2 +jeff rector,1 +burkut,9 +joe robinson,1 +turtle flambeau flowage,1 +moves like jagger,3 +turbaco,1 +oghuz turk,2 +latent human error,5 +square number,17 +rugby football league championship third division,2 +altoona pennsylvania,23 +circus tent,1 +satirical novel,1 +claoxylon,1 +barbaros class frigate,4 +oyer and terminer,2 +telephone numbers in the bahamas,1 +thomas c krajeski,2 +mv glenachulish,1 +sports broadcasting contracts in australia,3 +car audio,1 +ted lewis,2 +eric bogosian/robotstxt,2 +furman university japanese garden,1 +jed clampett,2 +flintstone,2 +c of tranquility,2 +rutali,2 +berkhamsted place,1 +wissam ben yedder,13 +nt5e,1 +erol onaran,1 +allium amplectens,1 +the three musketeers,2 +north eastern alberta junior b hockey league,1 +doggie daddy,1 +lauma,1 +the love racket,1 +eta hoffman,1 +ryans four,3 +omerta – city of gangsters,1 +humberview secondary school,2 +parels,1 +the descent,1 +evgenia linetskaya,1 +manhunt international 1994,1 +american society of animal science,1 +american samoa national rugby union team,1 +faster faster,1 +all creatures great and small,1 +mama said knock you out,9 +rozhdestveno memorial estate,2 +wizard of odd,1 +lugalbanda,4 +beardsley minnesota,1 +the rogue prince,10 +uss escambia,1 +stormy weather,3 +couleurs sur paris,1 +madrigal,4 +colin tibbett,1 +lemelson–mit prize,2 +phonetical singing,1 +glucophage,3 +suetonius,10 +ungra,1 +black and white minstrel,1 +woolwich west by election 1975,1 +trolleybuses in wellington,2 +jason macdonald,3 +ussr state prize,2 +robert m anderson,1 +kichijōji,1 +apache kid wilderness,1 +sneaky pete,8 +edward knight,1 +fabiano santacroce,1 +hemendra kumar ray,1 +sweat therapy,1 +stewart onan,2 +israel–turkey relations,1 +natalie krill,5 +clinoporus biporosus,1 +kosmos 2470,2 +vladislav sendecki,1 +healthcare in madagascar,1 +template talk 2010 european ryder cup team,1 +richard lyons,1 +transfer of undertakings regs 2006,3 +image processor,3 +alvin wyckoff,1 +kōbō abe,1 +kettle valley rail trail,1 +my baby just cares for me,3 +u28,1 +western australia police,10 +scincidae,1 +partitionism,1 +glenmorangie distillery tour,1 +river cave,1 +szilárd tóth,1 +i dont want nobody to give me nothing,1 +city,67 +annabel dover,2 +placebo discography,8 +showbiz,8 +solio ranch,1 +loan,191 +morgan james,10 +international federation of film critics,3 +the frankenstones,2 +pastor bonus,1 +billy purvis,1 +the gunfighters,1 +sandefjord,2 +ohio wine,2 +for the love of a man,1 +drifters,10 +ilhéus,1 +bikini frankenstein,1 +subterranean homesick alien,1 +chemical nomenclature,17 +great wicomico river,1 +ingrid caven,1 +japanese destroyer takanami,1 +nosler partition,1 +wagaman northern territory,1 +slovak presidential election 2019,1 +fuggerei,12 +al hibah,1 +irish war of independence,2 +joan smallwood,1 +anthony j celebrezze jr,1 +mercedes benz m130 engine,2 +phineas and ferb,2 +belgium womens national football team,3 +reynevan,1 +joe,1 +alan wilson,1 +epha3,1 +belarus national handball team,1 +phaedra,14 +move,2 +amateur rocketry,3 +epizootic hemorrhagic disease,5 +prague derby,4 +basilica of st thérèse lisieux,1 +pompeianus,1 +solved game,3 +tramacet,19 +essar energy,3 +lumbar stenosis,1 +part,24 +hải vân tunnel,1 +vsm group,3 +walter hooper,2 +consumer needs,1 +bell helicopter,18 +launde abbey,2 +ramune,10 +declarations of war during world war ii,1 +saint laurent de la salanque,1 +balkenbrij,1 +balgheim,1 +out of the box,13 +cappella,1 +national pharmaceutical pricing authority,4 +friend and foe,1 +new democracy,1 +eastern phoebe,2 +isipum of geumgwan gaya,1 +tel quel,1 +traveler,12 +superbeast,1 +oddsac,1 +zamora spain,1 +declaration of state sovereignty of the russian soviet federative socialist republic,1 +chumash painted cave state historic park california,3 +zentiva,1 +british rail class 88,5 +west indies cricket board,3 +pauli jørgensen,1 +punisher kills the marvel universe,7 +william de percy,1 +vehicle production group,4 +uc irvine anteaters mens volleyball,2 +dong sik yoon,1 +hyæna,2 +canadian industries limited,1 +mr ii,1 +jim muhwezi,1 +citizen jane,2 +night and day concert,1 +double precision floating point format,2 +herbal liqueurs,1 +the fixed period,5 +pip/taz,1 +lesser caucasus,2 +uragasmanhandiya,2 +alternative words for british,2 +khuzaima qutbuddin,1 +helmut balderis,2 +wesley r edens,1 +scott sassa,4 +mutant mudds,3 +east krotz springs louisiana,1 +leonard frey,3 +counting sort,15 +leandro gonzález pírez,2 +shula marks,1 +sierville,1 +california commission on teacher credentialing,1 +raymond loewy,10 +beevor foundry,1 +dog snapper,2 +hitman contracts,5 +eduard herzog,1 +wittard nemesis of ragnarok,1 +cape may light,1 +al saunders,3 +distant earth,2 +beam of light,2 +arent we all?,1 +veridicality,1 +private enterprise,3 +rambhadracharya,3 +dps,5 +beckdorf,1 +rúaidhrí de valera,1 +vivian bang,3 +sugar pine,1 +vn parameswaran pillai,1 +henry ross perot sr,1 +the arcadian,1 +the record,6 +g turner howard iii,1 +oleksandr usyk,12 +mumbai suburban district,5 +vicente dutra,1 +paean,1 +scottish piping society of london,1 +ingot,11 +alex obrien,6 +autonomous counties of china,1 +kaleorid,1 +remix & repent,3 +gender performativity,7 +godheadsilo,1 +tonsilloliths,1 +la dawri,1 +kiran more,3 +billboard music award for woman of the year,1 +tahitian ukulele,1 +buick lacrosse,14 +draft helen milner jury sent home for the night,2 +history of japanese cuisine,6 +time tunnel,1 +albert odyssey 2,1 +oysters rockefeller,4 +jim mahon,1 +evolutionary invasion analysis,1 +sunk cost fallacy,3 +universidad de manila,1 +morgan crucible,1 +southern miss golden eagles football,2 +horatio alger,13 +biological psychopathology,1 +hollywood,115 +product manager,21 +thomas burgh 3rd baron burgh,1 +stan hack,1 +peloponesian war,1 +republic of china presidential election 2004,2 +sanitarium,4 +growthgate,1 +samuel e anderson,1 +bobo faulkner,1 +kaffebrenneriet,1 +monponsett pond seaplane base,1 +powers of horror,3 +viburnum burkwoodii,1 +new suez canal,5 +gerardo ortíz,2 +japhia life,1 +paul pastur,1 +fuller craft museum,1 +nomal valley,1 +inaugural address,1 +saint Étienne du vigan,1 +lip ribbon microphone,2 +mary cheney,2 +piebald,6 +kadambas,1 +transportation in omaha,7 +before the league,1 +feltham and heston by election 2011,1 +aboriginal music of canada,3 +dnssec,6 +sshtunnels,1 +robin benway,1 +swimming at the 1968 summer olympics – mens 4 x 200 metre freestyle relay,1 +commission internationale permanente pour lepreuve des armes à feu portatives,3 +death rock,1 +hugo junkers,6 +gmt,3 +keanu reeves,2 +beverly kansas,1 +charlotte blair parker,1 +kids,5 +weight bench,1 +kiasmos,8 +basque country autonomous basketball team,1 +gideon toury,2 +gugak/,1 +texass 32nd congressional district,2 +have you ever been lonely,1 +take the weather with you,1 +chukchi,1 +the magicians wife,1 +juan manuel bordeu,1 +port gaverne,1 +music for films iii,1 +northern edo masquerades,1 +hang gliding,15 +marine corps logistics base barstow,2 +century iii mall,1 +peter tarlow,1 +thermal hall effect,1 +david ogden stiers,18 +webmonkey,1 +five cereals,2 +osceola washington,1 +clover virginia,2 +sphinginae,2 +stuart brace,1 +al di meola discography,7 +sunflowers,1 +hasty generalization,4 +polish athletic association,1 +the purge 3,2 +bitetti combat mma 4,1 +hiroko nagata,2 +mona seilitz,1 +mixed member proportional representation,7 +rancho temecula,2 +sinai,1 +norrmalmstorg robbery,5 +silesian walls,1 +floyd stahl,1 +gary becker,1 +knowledge engineering,5 +port of mobile,1 +luckiest girl alive,2 +ilya rabinovich,1 +bridge,3 +el general,3 +cornerstone schools,1 +gozmo,1 +charles courtney curran,1 +broker,32 +us senate committee on banking housing and urban affairs,2 +retroversion of the sovereignty to the people,1 +giorgi baramidze,1 +lars grael,1 +abdul qadir,3 +pgrep,2 +category talk seasons in danish womens football,1 +malus sieversii,1 +god squad,4 +category of acts,1 +melkote,1 +linda langston,1 +sherry romanado,1 +montana sky,8 +history of burkina faso,1 +iso 639 kxu,1 +los angeles fire department museum and memorial,1 +recognize,1 +der bewegte mann,6 +davy pröpper,1 +outline of vehicles,2 +gesta francorum,1 +sidney w pink,1 +ronald pierce,1 +martin munkácsi,1 +nord noreg,1 +accounting rate of return,7 +urwerk,1 +albert gallo,1 +antennaria dioica,3 +transport in sudan,2 +fladry,1 +cumayeri,1 +bennington college,11 +pêro de alenquer,2 +sixth man,1 +william i of aquitaine,1 +radisson diamond,1 +belgian united nations command,1 +venus genetrix,1 +sayesha saigal,14 +inverse dynamics,2 +national constitutional assembly,1 +honey bear,4 +certosa di pavia,2 +selective breeding,31 +let your conscience be your guide,1 +han hyun jun,1 +closed loop,8 +template talk golf major championships master,1 +twin oaks community virginia,1 +red flag,3 +housing authority of new orleans,2 +joice heth,4 +toñito,1 +ivan pavlov,2 +madanapalle,4 +ptat,1 +renger van der zande,1 +anaerobic metabolism,2 +patrick osullivan,1 +shirakoya okuma,1 +permian high school,9 +thomas h ford,1 +southfield high school,1 +religion in kuwait,2 +nathrop colorado,1 +hefner hugh m,1 +whitney bashor,1 +pope shenouda iii of alexandria,7 +thomas henderson,1 +tokka and rahzar,13 +windows thumbnail cache,3 +consumer council for water,1 +sake bombs and happy endings,1 +lothlórien,1 +the space bar,4 +sakuma rail park,1 +oas albay,3 +dan frankel,1 +cliff hillegass,1 +iron sky,12 +pentile matrix family,1 +oregon system,1 +california sea lion,7 +jeanneau,2 +meadowhall interchange,1 +lille catholic university,1 +nuñomoral,1 +vending machine,30 +xarelto,1 +jonbenét ramsey,3 +progresso castelmaggiore,1 +tacticity,6 +wing arms,1 +gag,2 +hank greenberg,8 +garda síochána,14 +puggy,1 +p sainath,1 +the year of living dangerously,9 +army reserve components overseas training ribbon,1 +hmas nestor,1 +john beckwith,1 +florida constitution,2 +yonne,3 +benoît richaud,1 +mamilla pool,2 +gerald bull,14 +david halberstam,12 +my fair son,2 +ncaa division iii womens golf championships,1 +anniela,1 +king county,1 +kamil jankovský,1 +synaptic,3 +rab,6 +switched mode regulator,1 +history of biochemistry,1 +halaf,2 +henry colley,1 +co postcode area,3 +social finance uk,1 +cercospora,2 +the dao,1 +unité radicale,2 +shinji hashimoto,3 +tommy remengesau,3 +isobel gowdie,2 +mys prasad,9 +national palace museum of korea,1 +basílica del salvador,2 +no stone unturned,2 +walton group,1 +foramen ovale,1 +slavic neopaganism,1 +iowa county wisconsin,3 +melodi grand prix junior,1 +jarndyce and jarndyce,3 +talagunda,1 +nicholas of autrecourt,1 +substitution box,3 +the power of the daleks,1 +real gas,6 +edward w hincks,1 +kangxi dictionary,5 +natural world,1 +h h asquith,21 +francis steegmuller,1 +sasha roiz,3 +media manipulation,1 +looking for comedy in the muslim world,2 +bytown,4 +previsualization,1 +rita ora discography,11 +kiersey oklahoma,1 +henry greville 3rd earl of warwick,1 +draft,4 +phenolate,1 +i believe,1 +virologist,1 +relief in abstract,1 +eastern medical college,1 +purveyance,2 +ascending to infinity,2 +sportstime ohio,2 +church of wells,1 +ivory joe hunter,1 +wayne mcgregor,2 +luna 17,4 +viscount portman,2 +wikipedia talk wikipedia signpost/2009 07 27/technology report,1 +negramaro,1 +barking owl,2 +i need you,2 +brockway mountain drive,1 +template talk albatros aircraft,1 +future shock,11 +china national highway 317,1 +laurent gbagbo,7 +plum pudding model,18 +league of the rural people of finland,1 +dundees rising,1 +nikon f55,1 +olympic deaths,5 +gemma jones,19 +hafsa bint al hajj al rukuniyya,1 +personal child health record,1 +logic in computer science,11 +bhyve,3 +hothouse,1 +log house,6 +library of celsus,2 +the lizzie bennet diaries,1 +leave this town the b sides ep,1 +estimated time of arrival,8 +chariotry in ancient egypt,2 +american precision museum,1 +dimos moutsis,1 +scriptlet,1 +something in the wind,1 +sharka blue,1 +time on the cross the economics of american negro slavery,1 +tomislav kiš,1 +khalid islambouli,7 +bankruptcy abuse prevention and consumer protection act,7 +gračanica bosnia and herzegovina,2 +jungs theory of neurosis,5 +mgm animation,1 +soviet support for iran during the iran–iraq war,3 +native american,1 +template talk nigeria squad 1994 fifa world cup,1 +norwegian lutheran church,4 +adia barnes,1 +coatings,1 +mehdi hajizadeh,1 +the dead matter cemetery gates,1 +fuzzy little creatures,1 +waje,7 +anji,1 +heinz haber,1 +turkish albums chart,1 +sebastian steinberg,1 +price fixing cases,2 +bellator 48,1 +edgar r champlin,1 +otto hermann leopold heckmann,1 +bishops stortford fc,4 +stern–volmer relationship,6 +morgan quitno,2 +five star general,1 +iso 13406 2,1 +black prince,11 +leopard kung fu,1 +felix wong,5 +mary claire king,6 +alvar lidell,1 +playonline,1 +infantry branch,1 +andrew pattison,1 +john turmel,1 +kent,74 +edwin palmer hoyt,1 +captivity narratives,1 +jaguar xj220,1 +hms tanatside,2 +new faces,2 +edward levy lawson 1st baron burnham,1 +samuel woodfill,3 +jewish partisans,9 +abandonware,16 +early islamic philosophy,2 +sleeper cell,5 +media of africa,2 +san andreas,3 +luxuria,2 +egon hostovský,3 +pelagibacteraceae,1 +martin william currie,1 +borescope,21 +narratives of islamic origins the beginnings of islamic historical writing,1 +lecompton constitution,2 +axé bahia,2 +paul goodman,1 +template talk washington nationals roster navbox,1 +a saucerful of secrets,2 +david carol macdonnell mather,1 +portal buddhism,3 +florestópolis,1 +alecs+golf+ab,1 +bank alfalah,1 +frank pellegrino,3 +loutre,1 +erp4it,2 +monument to joe louis,2 +witch trial of nogaredo,1 +sabrina santiago,2 +no night so long,3 +helena carter,1 +renya mutaguchi,3 +yo yogi,4 +bolivarian alliance for the americas,3 +cooper boone,1 +uss iowa,24 +mitsuo iso,2 +cranberry,1 +batrachotomus,1 +richard lester,5 +bermudo pérez de traba,1 +rosser reeves ruby,1 +telecommunications in morocco,4 +i a richards,1 +nidhal guessoum,1 +lilliefors test,6 +the silenced,5 +mambilla plateau,1 +sociology of health and illness,3 +tereza chlebovská,2 +bismoll,3 +kim suna,1 +scream of the demon lover,1 +joan van ark,7 +intended nationally determined contributions,6 +dietary supplement,16 +last chance mining museum,1 +savoia marchetti s65,1 +if i can dream,1 +maharet and mekare,4 +nea anchialos national airport,2 +american journal of digestive diseases,1 +chance,2 +lockheed f 94c starfire,1 +the game game,1 +kuzey güney,3 +semmering base tunnel,1 +three mile island,1 +evaluation function,1 +robert mckee,4 +carmelo soria,1 +moneta nova,1 +pīnyīn,1 +international submarine band,3 +elections in the bahamas,5 +powell alabama,1 +kmgv,1 +charles stuart duke of kendal,2 +echo and narcissus,7 +trencrom hill,1 +ashwini dutt,1 +the herzegovina museum,1 +liverpool fc–manchester united fc rivalry,12 +kerber,1 +flakpanzer 38,8 +demographics of bihar,2 +rico reeds,1 +vandenberg afb space launch complex 3,1 +wiesendangen,1 +lamm,1 +allen doyle,2 +anusree,5 +broad spectrum,1 +bay middleton,2 +connect savannah,1 +history of immigration to canada,22 +waco fm,3 +nakano takeko,1 +murnau am staffelsee,2 +minarchy,1 +haymans dwarf epauletted fruit bat,1 +brachyglottis repanda,1 +associative,1 +mississippi aerial river transit,1 +stefano siragusa,2 +gregor the overlander,3 +marine raider,1 +pogorzans,1 +sportcity,2 +garancahua creek,1 +vincent dimartino,3 +ninja,2 +natural history museum of bern,1 +revolutionary catalonia,4 +chiayi,1 +alix strachey,3 +looe island,1 +college football usa 96,1 +off peak return,1 +minsk 1 airport,1 +evangelical lutheran church in burma,2 +riemann–roch theorem,1 +the comic strip,2 +vladimir istomin,1 +america again,2 +brown treecreeper,1 +american high school,1 +powerglide,2 +oolitic limestone,1 +daz1,1 +jarrow vikings,1 +pierre philippe thomire,1 +dorothy cadman,1 +gaston palewski,3 +twin river bridges,1 +im yours,1 +ambrose dudley 3rd earl of warwick,3 +ssim,2 +original hits,1 +cosmonaut,9 +special educational needs and disability act 2001,4 +will you speak this word,1 +history of wolverhampton wanderers fc,1 +don lawrence,1 +tokyo metropolitan museum of photography,1 +orduspor,1 +john lukacs,3 +patrice collazo,1 +lords resistance army insurgency,5 +ronald "slim" williams,5 +drivin for linemen 200,1 +nicolò da ponte,1 +bucky pope,1 +ewing miles brown,2 +ugly kid joe,28 +american flight 11,1 +louzouer,1 +district hospital agra,1 +jessica jane applegate,1 +sexuality educators,1 +serie a scandal of 2006,1 +at war with reality,1 +stephen wiltshire,13 +vechigen switzerland,1 +rikki clarke,3 +rayakottai,1 +permanent magnet electric motor,1 +qazi imdadul haq,1 +plywood,49 +ntr telugu desam party,1 +skin lightening,1 +royal natal national park,1 +uss mcdougal,2 +queen of the sun,1 +karanjachromene,1 +on 90,1 +enrique márquez,1 +siegfried and roy,1 +city manager,6 +wrdg,1 +why i am not a christian,3 +protein coding region,1 +royal bank of queensland gympie,1 +british invasions of the river plate,2 +yasufumi nakanoue,1 +magnetic man,1 +kickback,3 +tillandsia subg allardtia,1 +north american nr 349,1 +edict of amboise,1 +st andrew square edinburgh,2 +flag of washington,2 +timeless,2 +new york state route 125,3 +fudge,3 +single entry bookkeeping system,5 +refractive surgery,8 +bi monthly,1 +park high school stanmore,1 +norton anthology of english literature,1 +michael wines,1 +gaff rig,1 +kosmos 1793,1 +major facilitator superfamily,2 +talpur dynasty,1 +byron bradfute,1 +quercitello,1 +rcmp national protective security program,1 +ann kobayashi,1 +recurring saturday night live characters and sketches,3 +abraham hill,1 +nagapattinam district,4 +pidgeon,3 +mycalessos,1 +technical university of hamburg,1 +electric shock&ei=ahp0tbk0emvo gbe v2bbw&sa=x&oi=translate&ct=result&resnum=2&ved=0ceaq7gewaq&prev=/search?q=electric+shock&hl=da&biw=1024&bih=618&prmd=ivns,2 +aim 54 phoenix,18 +undercut,5 +gokhale memorial girls college,1 +digital penetration,19 +centre for peace studies tromsø,1 +richie williams,1 +walloon region,1 +albany city hall,2 +maxine carr,4 +anglosphere,18 +effect of world war i on children in the united states,1 +josh bell,1 +german thaya,1 +brian murphy,3 +marguerite countess of blessington,1 +leak,1 +bubble point,5 +international federation of human rights,1 +clubcorp,2 +greater philadelphia,1 +daniel albright,1 +macas,1 +roses,4 +woleu ntem,1 +shades of blue,1 +say aah,2 +curtiss sbc,1 +ion andone,1 +firstborn,1 +marringarr language,2 +ann e todd,1 +native american day,4 +stand my ground,1 +bavington,1 +classification of indigenous peoples of the americas,2 +always,6 +leola south dakota,1 +psycilicibin,2 +roy rogers,1 +marmalade,1 +national prize of the gdr,1 +shilp guru,1 +m2 e 50,1 +jorge majfud,2 +cutter and bone,1 +william steeves,1 +lisa swerling,2 +grace quigley,5 +telecommunications in yemen,1 +rarotonga international airport,7 +cycling at the 2010 central american and caribbean games,2 +mazda b3000,1 +hanwencun,1 +adurfrazgird,1 +ivan ivanov vano,1 +yhwh,1 +qarshi,4 +oshibori,2 +uppada,1 +iain clough,1 +painted desert,7 +tugzip,1 +my little pony fighting is magic,143 +pantheon,2 +chinese people in zambia,1 +yves saint laurent,3 +texas helicopter m79t jet wasp ii,1 +forever reign,1 +charlotte crosby,32 +ealdormen,9 +copper phosphate,2 +mean absolute difference,5 +hôtel de soubise,5 +josh rees,2 +non commissioned officer,70 +gb jones,1 +im feeling you,2 +book of shadows,9 +brain trauma,1 +sulpitius verulanus,1 +vikranth,5 +space adaptation syndrome,6 +united states presidential election in hawaii 1988,1 +joe garner,4 +river suir bridge,2 +the beach boys medley,1 +joyce castle,1 +christophe wargnier,1 +ik people,2 +sketch show,1 +buena vista police department,1 +file talk layzie bone clevelandjpg,1 +gillian osullivan,3 +prince albert of saxe coburg and gotha,2 +berean academy,1 +motorcraft quality parts 500,1 +frederick law olmsted,21 +born this way,9 +sterling virginia,4 +if wishes were horses beggars would ride,1 +section mark,1 +tapi,1 +navy cross,1 +housekeeper,1 +gian battista marino,1 +planá,1 +chiromantes haematocheir,1 +colonial life & accident insurance company,4 +aduana building,2 +kim johnston ulrich,1 +berkelium 254,1 +m&t bank corp,2 +sit up,1 +sheknows,1 +phantom lady,1 +bruce kamsinky,1 +commercial drive,1 +chinese people in the netherlands,1 +sylvia young theatre school,4 +influenza a virus subtype h2n3,1 +dracut,2 +nate webster,1 +vila velebita,1 +uaz patriot,4 +democratic unification party,1 +alexander slidell mackenzie,1 +portland mulino airport,1 +first person shooter,2 +the temporary widow,1 +terry austin,1 +the foremans treachery,1 +hms blenheim,1 +sodium dichloro s triazinetrione,1 +kurt becher,1 +cumberland gap tn,1 +newton cotes,1 +daphne guinness,6 +internal tide,1 +god and gender in hinduism,2 +howlin for you,1 +stellarator,14 +cavea,3 +faye ginsburg,1 +lady cop,3 +template talk yugoslavia squad 1986 fiba world championship,1 +solidarity economy,1 +second presidency of carlos andrés pérez,1 +bora bora,71 +xfs,1 +christina bonde,1 +agriculture in australia,20 +scenic drive,1 +richard mantell,1 +motordrome,1 +broadview hawks,1 +misty,2 +international bank of commerce,2 +istanbul sapphire,5 +changkat keruing,1 +the hotel inspector unseen,1 +tharwa australian capital territory,2 +strauss,2 +shock film,1 +ulick burke 1st marquess of clanricarde,2 +valencia cathedral,5 +kay bojesen,1 +palogneux,1 +texas beltway 8,1 +jackie walorski,7 +capital punishment in montana,1 +byte pair encoding,2 +upper deerfield township new jersey,2 +lucca comics & games,1 +lee chae young,1 +czar alexander ii,1 +kool ad,6 +leopold van limburg stirum,1 +john dunn,1 +policeman,2 +what dreams may come,3 +grant ginder,1 +chieverfueil,2 +long island express,1 +malmö sweden,2 +song for my father,1 +see saw,2 +jean jacques françois le barbier,5 +do rag,11 +dsb bank,2 +davical,6 +cervical cap,1 +gershon yankelewitz,1 +the last hurrah,4 +category talk educational institutions established in 1906,1 +tour pleyel,1 +león klimovsky,1 +phyoe phyoe aung,1 +phil sawyer,2 +android app //orgwikipedia/http/enmwikipediaorg/wiki/swiftkey,1 +deontological,3 +juan dixon,12 +robert pine,4 +alexander tilloch galt,2 +common tailorbird,12 +derailed,7 +mike campbell,3 +terminator 2 3 d battle across time,3 +technische universität münchen,4 +baloana,1 +echis leucogaster,1 +lahore pigeon,1 +william de beauchamp 9th earl of warwick,2 +erin go bragh,14 +economics u$a,1 +villafranca montes de oca,1 +pope eusebius,2 +martin kruskal,1 +félix de blochausen,1 +jeff jacoby,1 +mark krein,2 +travis wester,2 +fort louis de la louisiane,1 +weddingwire,2 +ping,54 +don swayze,8 +steve hamilton,3 +rhenish,1 +winrar,3 +births in 1561,4 +copyright law of the netherlands,2 +floodland,9 +tamil nadu tourism development corporation,1 +dolls house,1 +chkrootkit,1 +search for the hero,1 +avenal,1 +tini,2 +patamona,1 +aspendos international opera and ballet festival,2 +felix cora jr,5 +yellow cardinal,2 +antony jay,1 +conda,1 +a tramp shining,1 +william miller,1 +holomictic lake,2 +growler,2 +the violence of summer,1 +meerschaum,3 +cd138,1 +karl friedrich may,1 +history of iraq,2 +henry ford,139 +rumwold,1 +beatrice di tenda,1 +blaze,1 +nick corfield,1 +walt longmire,5 +eleazar maccabeus,1 +business edition,1 +karl oyston,4 +gypsy beats and balkan bangers,1 +fa premier league 2004 05,1 +agawan radar bomb scoring site,1 +the hall of the dead,1 +combat training centre,1 +moroccan portuguese conflicts,2 +pokipsy,1 +minor characters in csi crime scene investigation,1 +miguel molina,1 +buckypaper,2 +magazine,4 +forget about it,2 +marco schällibaum,1 +r d smith,1 +nfl playoff results,2 +four score,1 +centenary bank,2 +london borough of camden,12 +bhumij,1 +counter reformation/trackback/,1 +billy volek,1 +cover song,1 +awang bay,1 +douglas fitzgerald dowd,3 +architecture of ancient greece,5 +ny1,2 +academy award for best visual effects,3 +history of the mbta,2 +triangle group,1 +charles r fenwick,1 +berenice i of egypt,1 +window detector,1 +corruption perception index,1 +leffrinckoucke,1 +lee anna clark,1 +burndy,2 +inset day,2 +american association of motor vehicle administrators,1 +ckm matrix,1 +angiopoietin 1,1 +steven marsh,1 +open reading frame,27 +telesystems,1 +pastoral poetry,1 +west wycombe park,2 +lithium,7 +nogales international airport,1 +wajków,1 +sls 1,1 +trillo,2 +max s,1 +verndale,1 +yes sir i can boogie,1 +blog spam,10 +daniel veyt,1 +william brown,3 +takami yoshimoto,1 +josh greenberg,4 +geoffrey heyworth 1st baron heyworth,1 +medeina,3 +anja steinlechner,1 +riviera beach florida,2 +gerris wilkinson,1 +north american lutheran church,1 +paul dillett,11 +proto euphratean language,1 +best selling books,2 +pumpellyite,1 +business objects,1 +fodor,2 +xanadu,3 +london river,1 +draft juan de orduña,2 +barriemore barlow,3 +jew harp,1 +birmingham,1 +titus davis,1 +march 2012 gaza–israel clashes,1 +energy demand management,2 +aquarium of the americas,3 +tto,1 +l h c tippett,1 +optical fiber,88 +onești,2 +stanley ntagali,1 +prussian blue,1 +bill kovach,2 +hip pointer,3 +alessandra amoroso,4 +fleet racing,1 +navy maryland rivalry,1 +cornering force,1 +the mighty quest for epic loot,5 +katalyst,2 +the beef seeds,1 +shack out on 101,1 +aircraft carrier operations,1 +overseas province,2 +institute of state and law,1 +light truck,5 +plastics in the construction industry,2 +little zizou,2 +congenic,2 +adriaen van utrecht,1 +brian mcgrath,3 +parvati,1 +jason gwynne,1 +kphp,1 +miryusif mirbabayev,1 +kōriyama castle,3 +the making of a legend gone with the wind,2 +shot traps,1 +awa tag team championship,1 +littlebourne,2 +franchot tone,4 +john dudley 2nd earl of warwick,2 +mass spec,1 +final fantasy vi,44 +gerry ellis,1 +adon olam,3 +man 24310,1 +p n okeke ojiudu,1 +unqi,1 +snom,1 +bruce bagemihl,1 +category talk animals described in 1932,1 +metalist oblast sports complex,1 +colley harman scotland,1 +suka,1 +anita sarkeesian,81 +kazakhstan national under 17 football team,1 +ym,2 +matt barnes,1 +tour phare,1 +bellus–claisen rearrangement,2 +turkey at the 2012 summer olympics,1 +irréversible,32 +umbilical nonseverance,1 +wood stave,1 +indian pentecostal church of god,1 +camponotus nearcticus,3 +john tesh,13 +syncline,4 +skins,50 +kelsey manitoba,1 +alkayida,2 +polyglotism,17 +forensic statistics,2 +ram vilas sharma,8 +pearl jam,71 +dj max fever,1 +islamic view of miracles,5 +kds,1 +alabama cavefish,1 +johanna drucker,1 +tom wolk,4 +rottenburg,2 +goshen connecticut,2 +maker media,1 +morphett street adelaide,1 +keystone hotel,1 +baseball hall of fame balloting 2005,1 +gongzhuling south railway station,1 +ss charles bulfinch,1 +sig mkmo,1 +cartman finds love,2 +embassy of syria in washington dc,1 +charles prince of wales,175 +teachings of the prophet joseph smith,1 +charles iv,1 +alethea steven,1 +type i rifle,2 +a peter bailey,1 +brain cancer,1 +eric l clay,2 +jett bandy,1 +moro rebellion,9 +eustachów,1 +avianca el salvador,2 +dont stop the party,4 +reciprocal function,1 +dagmar damková,1 +hautmont,1 +penguin english dictionary,2 +waddie mitchell,1 +technician fourth grade,3 +hot girls in love,1 +critérium du dauphiné,59 +love song,2 +roger ii,2 +whitbread book award,1 +thomas colepeper 2nd baron colepeper,2 +a king and no king,1 +big fish & begonia,5 +mayville new york,2 +molecularity,1 +ed romero,1 +one watt initiative,3 +jeremy hellickson,2 +william morgan,1 +giammario piscitella,1 +eastern lesser bamboo lemur,1 +padre abad district,1 +don brodie,1 +facts on the ground,1 +undeniable evolution and the science of creation,1 +john of giscala,1 +bryce harper,45 +gabriela irimia,1 +empire earth mobile,1 +the queen vic,1 +helen rowland,1 +mixed nuts,5 +malacosteus niger,2 +george r r martin/a song of ice and fire,1 +brock osweiler,11 +tough,1 +outline of agriculture,4 +sea wolf,1 +mo vaughn,4 +the brood of erys,1 +composite unit training exercise,1 +isabella acres,4 +the jersey,5 +coal creek bridge,1 +habana libre,1 +nicole pulliam,1 +john shortland,1 +daniel pollen,1 +magic kit,1 +baruch adonai l&,1 +a daughters a daughter,2 +laughlin nevada,11 +tubercule,1 +louis laurie,1 +internet boom,3 +conversion of paul,1 +comparison of software calculators,1 +choctaw freedmen,2 +josh eady,1 +hôpital charles lemoyne,2 +u mobile,2 +john tomlinson,1 +baré esporte clube,2 +tuğçe güder,2 +highams park railway station,4 +newport east,1 +clothing industry,6 +scott rosenberg,6 +my 5 wives,2 +matt godfrey,1 +port ellen,2 +winecoff hotel fire,1 +fide world chess championship 2005,2 +lara piper,1 +the little mermaid,1 +foxmail,6 +penn lyon homes,1 +stockholm opera,1 +american journal of theology,1 +bernard gorcey,3 +rodger collins,1 +clarkeulia sepiaria,1 +korean era name,3 +melide ticino,1 +unknown to no one,1 +asilinae,1 +scânteia train accident,1 +parti de la liberté et de la justice sociale,1 +falkland islands sovereignty dispute,13 +castile,10 +french battleship flandre,1 +nils taube,1 +anisa haghdadi,1 +william tell told again,2 +magister,3 +zgc 7,1 +national agricultural cooperative marketing federation of india,3 +les bingaman,1 +chebfun,1 +portal current events/august 2014,2 +eparchy of oradea mare,1 +tempo and mode in evolution,2 +seili,1 +boniface,3 +supportersvereniging ajax,1 +support team,1 +lactometer,1 +twice as sweet,1 +spruce pine mining district,2 +banknotes of the east african shilling,1 +cerebral cortex,3 +tagalogs,1 +german diaspora,8 +grammelot,1 +max a,1 +category talk vienna culture,1 +cheung kong graduate school of business,1 +three certainties,1 +multani,3 +barry callebaut,15 +joanne mcneil,1 +z grill,4 +commonwealth of australia constitution act 1900,1 +ganzorigiin mandakhnaran,1 +peter h schultz,1 +ea pga tour,3 +scars & memories,1 +exodus from lydda,1 +states reorganisation act 1956,4 +guy brown,1 +horsebridge,1 +arthur mafokate,1 +aldus manutius,5 +american daylight,3 +jean chaufourier,2 +edmond de caillou,1 +hms iron duke,9 +displeased records,1 +quantum turing machine,3 +ncert textbook controversies,2 +dracs,1 +beyrouth governorate,1 +staphylococcus caprae,1 +tankard,2 +surfaid international,1 +hohenthurn,2 +mission x 41,1 +professional wrestling hall of fame,2 +george mountbatten 4th marquess of milford haven,2 +athletics at the 2012 summer paralympics womens club throw f31 32/51,1 +knots and crosses,1 +edge vector,1 +philippe arthuys,1 +baron raglan,1 +odell beckham jr,3 +elfriede geiringer,1 +hyflux,1 +author level metrics,2 +ieee fellow,1 +pori brigade,3 +polyphenol antioxidant,1 +the brothers,8 +kakaji Ōita,1 +shyam srinivasan,2 +shahid kapoor,88 +chuckie williams,1 +colonial,4 +roman spain,1 +convolvulus pluricaulis,1 +william j burns international detective agency,1 +accessibility for ontarians with disabilities act 2005,1 +linguist,1 +agonist,2 +xiaozi,1 +holker hall,1 +novatium,1 +alois jirásek,1 +lesser crested tern,1 +names of european cities in different languages z,1 +hydrogen cooled turbogenerator,2 +indian airlines flight 257,1 +united states attorney for the northern district of indiana,1 +this is us,11 +transaction capabilities application part,1 +culiacán,6 +hash based message authentication code,65 +heinz murach,1 +dual citizen,2 +zhizn’ za tsarya,1 +gabriel taborin technical school foundation inc,1 +deaths in july 1999,1 +aponi vi arizona,1 +amish in the city,2 +goodbye cruel world,1 +st augustine grass,10 +moesi,1 +violette leduc,3 +methyl formate,9 +you walk away,1 +the traveler,1 +bond,89 +moa cuba,3 +hebrew medicine,1 +women in the russian and soviet military,2 +help log,2 +cuillin,5 +back fire,14 +salesrepresentativesbiz,1 +hogsnort rupert,1 +dwarf minke whale,1 +embassy of albania ottawa,1 +cotai water jet,1 +st lucie county florida,8 +wesselman,1 +american indian art,1 +richard arkless,1 +trolleybuses in bergen,1 +vama buzăului,1 +far east movement,9 +threes a crowd,1 +insane,3 +linux technology center,4 +patty duke,24 +smuckers,1 +kapalua,1 +amf futsal world cup,5 +umes chandra college,1 +jnanappana,2 +bar bar bar,1 +beretta m951,2 +libertarian anarchism,1 +fart proudly,4 +peyton place,5 +phase detection autofocus,1 +cavalry in the american civil war,9 +class stratification,1 +battle of cockpit point,1 +regiment van heutsz,2 +ana rivas logan,1 +nenya,1 +westland wah 64 apache,1 +roslyn harbor new york,3 +august wilhelm von hofmann,1 +professional baseball,2 +douglas feith,1 +pogrom,21 +aušra kėdainiai,1 +pseudopeptidoglycan,4 +arquà petrarca,1 +wayampi,1 +conservative government 1866 1868,1 +world naked bike ride,28 +fruitvale oil field,2 +shuttle buran,1 +robert c pruyn,1 +totem,1 +megalotheca,1 +nkechi egbe,1 +james p comeford,1 +heavens memo pad,7 +cauca valley,1 +jungfraujoch railway station,2 +seo in guk,24 +bold for delphi,1 +multiple frames interface,1 +zhenli ye gon,6 +kyabram victoria,1 +two stars for peace solution,1 +couette flow,9 +new formalism,2 +template talk 1930s comedy film stub,1 +template talk scream,1 +joona toivio,4 +iaaf silver label road race,1 +super bowl xxviii,5 +i aint never,1 +paul little racing,1 +jacobite rising of 1715,3 +katherine archuleta,1 +programmable logic device,12 +footsteps of our fathers,2 +once upon a tour,1 +tauck,1 +budapest memorandum on security assurances,5 +prostitution in chad,2 +bebedouro,2 +vice,2 +madredeus,1 +p diddy,1 +princess alice of the united kingdom,20 +jerry hairston jr,1 +neo noir,3 +self evaluation motives,1 +relativity the special and the general theory,2 +the sign of four,3 +kevin deyoung,1 +robin long,1 +mokshaa helsa,1 +nagaon,1 +aniceto esquivel sáenz,1 +sda,2 +german battlecruiser gneisenau,1 +assisted reproductive technology,12 +cmmg,1 +vision of you,1 +keshia chanté discography,1 +biofuel in the united kingdom,1 +katinka ingabogovinanana,1 +hutt valley,1 +garwol dong,1 +tunceli province,3 +edwin bickerstaff,1 +halloween 3 awesomeland,1 +canadian records in track and field,1 +ubisoft são paulo,1 +midstream,16 +jethro tull,4 +childhoods end,55 +ss rohilla,1 +lagranges four square theorem,6 +bucky pizzarelli,3 +jannik bandowski,80 +guðni Ágústsson,1 +multidimensional probability distribution,1 +brno–tuřany airport,2 +broughtonia,5 +cold hands warm heart,1 +simone biles,32 +bf homes parañaque,2 +akaflieg köln ls11,3 +street fighter legacy,2 +beautiful kisses,1 +first modern olympics,1 +macbook air,1 +dublab,1 +silent night deadly night,6 +earth defense force 2025,2 +grant township carroll county iowa,1 +gary williams,1 +malmö aviation,1 +geographical pricing,2 +anaheim memorial medical center,1 +mary+mallon,1 +henry a byroade,1 +wawasan 2020,4 +eurovision dance contest,6 +lydia polgreen,1 +pilsen kansas,1 +colin sampson,1 +neelamegha perumal temple,1 +james bye,2 +canadian federation of agriculture,1 +f w de klerk,34 +bob casey jr,3 +northport east,1 +elian gonzalez affair,1 +aleksei bibik,1 +anthony dias blue,1 +pyaar ke side effects,4 +fusako kitashirakawa,1 +cal robertson,4 +shandong national cultural heritage list,1 +police story 3 super cop,5 +the third ingredient,3 +dean horrix,1 +pico el león,1 +cesar chavez street,1 +prospered,1 +children in cocoa production,5 +gervase helwys,1 +binary digit,1 +kovai sarala,4 +mathematics and music,1 +macroglossum,1 +f gary gray,21 +broadsoft,2 +cachan,4 +bukkake,21 +church of st margaret of scotland,1 +christopher cockerell,3 +amsterdam oud zuid,1 +county of bogong,1 +intel mobile communications,1 +the legend of white fang,1 +millwright,19 +will buckley,1 +bill jelen,2 +template talk san francisco 49ers coach navbox,1 +amalia garcía,1 +because he lives,1 +air charts,1 +stade edmond machtens,1 +henry stommel,1 +dxgi,1 +misr el makasa sc,1 +chad price,2 +carl henning wijkmark,1 +acanthogorgiidae,1 +diqduq,1 +prelog strain,2 +crispin the cross of lead,4 +avraham adan,2 +barbershop arranging,1 +free x tv,1 +eric guillot,1 +kht,1 +never a dull moment,1 +lwów school of mathematics,1 +sears centre,3 +chin state,6 +van halen 2007 2008 tour,1 +robert weinberg,3 +fierté montréal,2 +vince jack,1 +heikki kuula,1 +architecture of the republic of macedonia,1 +glossary of education terms,1 +aleksandra szwed,1 +military history of europe,3 +exeter central railway station,1 +staroselye,1 +lee thomas,7 +saint peters square,2 +romanization of hispania,2 +file talk dodecahedrongif,1 +signed and sealed in blood,8 +colleges of worcester consortium,1 +district electoral divisions,1 +galkot,1 +king África,3 +monetary policy,57 +brp ang pangulo,2 +battle of mạo khê,1 +air tube,1 +ruth ashton taylor,2 +keith jensen,1 +headland alabama,1 +willie loomis,1 +interactive data extraction and analysis,2 +georgetown city hall,2 +chuck es in love,2 +weeksville brooklyn,1 +anatoly sagalevich,2 +browett lindley & co,1 +barnawartha victoria,1 +pop,2 +black balance,2 +aceratorchis,1 +emmeline pethick lawrence baroness pethick lawrence,1 +osso buco,1 +herminie cadolle,2 +telegram & gazette,2 +le van hieu,1 +pine honey,2 +nexvax2,1 +leicester north railway station,1 +jacqueline foster,1 +bill handel,3 +nizami street,1 +radke,1 +bob mulder,1 +ambroise thomas,4 +carles puigdemont i casamajó,1 +callable bond,6 +tesco metro,2 +mohan dharia,1 +great hammerhead,12 +vinko coce,3 +john mayne,1 +cobb cloverleaf,1 +uhlan,10 +giulio migliaccio,1 +belmont university,6 +rinucumab,1 +kearny high school,1 +chūgen,1 +stages,2 +boar%27s head carol,1 +knight of the bath,1 +ayres thrush,7 +sing hallelujah,1 +the tender land,2 +wholesale banking,1 +jean jacques perrey,5 +maxime bossis,2 +sherman records,1 +alan osório da costa silva,1 +fannie willis johnson house,1 +blacks equation,2 +levinthals paradox,2 +thomas scully,2 +necron,3 +university of alberta school of business,5 +lake shetek,1 +toby maduot,1 +gavriil golovkin,1 +sweetwater,3 +atlantic revolutions,2 +jaime reyes (comics,1 +kajang by election 2014,1 +mycotoxigenic,1 +san marco altarpiece,2 +line impedance stabilization network,2 +santiago hernández,1 +jazzland,3 +host–guest chemistry,4 +giovanni florio,2 +st marylebone school,1 +acqua fragile,1 +the horse whisperer,10 +don francis,1 +mike molesevich,1 +brad wright,1 +north melbourne football club,3 +brady dragmire,1 +margaret snowling,2 +wing chun terms,4 +mckey sullivan,1 +derek ford,1 +cache bus,1 +bernie grant arts centre,2 +amata francisca,1 +sinha,2 +larissa loukianenko,1 +oceans apart&sa=u&ved=0ahukewjw4n6eqdblahun7gmkhxxebd8qfgg4mag&usg=afqjcnhhjagrbamjgaxc7rpsso4i9z jgw,1 +anemone heart,2 +alison mcinnes,1 +juan lindo,1 +mahesh bhupati,1 +baháí faith in taiwan,5 +cinema impero,1 +template talk rob thomas,1 +likin,1 +science & faith,1 +fort saint elmo,3 +delhi kumar,6 +juha lallukka,1 +situational sexual behavior,2 +milligan indiana,1 +william em lands,1 +karl anselm duke of urach,2 +hérold goulon,1 +vedic mathematics,20 +move to this,1 +koussan,1 +floored,1 +raghu nandan mandal,1 +angels gods secret agents,1 +orthogonal,2 +the little house on the prairie,1 +chilean pintail,1 +guardian angel,2 +st leonard maryland,1 +green parties in the united kingdom,1 +time to say goodbye,1 +alba michigan,2 +harbourfront centre,1 +corner tube boiler,1 +consensus government,1 +ppru 1,1 +corporate anniversary,4 +sazerac company,5 +kyle friend,1 +bmw k1100lt,1 +pergola marche,1 +commonwealth of kentucky,2 +taiwan passport,2 +clare quilty,1 +domenico caprioli,1 +frank m hull,1 +cheng sui,2 +nazi board games,3 +spark bridge,1 +derrick thomas,6 +wunnumin 1,1 +emotion remixed +,4 +brian howard dix,2 +brigalow queensland,2 +burgi dynasty,1 +apolonia supermercados,1 +brandon lafell,2 +one day,24 +nara period,9 +template talk the land before time,1 +assyrians in iraq,1 +trade union reform and employment rights act 1993,2 +template talk evansville crimson giants seasons,1 +boys be smile / 目覚めた朝にはきみが隣に,2 +kapuloan sundha kecil,1 +human impact of internet use,1 +kolkata metro line 2,3 +saint pardoux morterolles,1 +carfin grotto,2 +samuel johnson prize,3 +french royal family,1 +android app //orgwikipedia/http/enmwikipediaorg/wiki/victoria park,1 +mazda xedos 9,1 +măiestrit,1 +petroleum economist,2 +penetration,2 +adrian rawlins,8 +plutonium 239,11 +culture of montreal,1 +british germans,2 +warszawa wesoła railway station,1 +lorenzo di bonaventura,6 +military ranks of estonia,1 +uss flint,8 +arthur f defranzo,1 +sadeh,1 +jammu and kashmir,3 +igor budan,2 +charmila,2 +choi,1 +mohammed ali khan walajah,1 +sourabh varma,1 +after here through midland,1 +martyn day,1 +justin larouche,1 +illinoiss 6th congressional district,4 +jackson wy,1 +tyson apostol,4 +mitch morse,1 +robert davila,1 +canons regular of saint john cantius,1 +giant girdled lizard,2 +cascade volcanoes,5 +fools day,1 +cordyline indivisa,1 +pueraria,2 +swiss folklore,4 +meretz,3 +united states senate elections 1836 and 1837,1 +baby i need your love/ easy come easy go,1 +butrus al bustani,2 +the lion the lamb the man,1 +rushikulya,1 +brickworks,3 +alliance party of kenya,1 +ludlow college,1 +internationalism,11 +ernest halliwell,1 +constantine phipps 1st marquess of normanby,1 +kari ye bozorg,1 +signal flow,4 +i beam,1 +devils lake,1 +union of artists of the ussr,2 +index of saint kitts and nevis related articles,1 +ethernet physical layer,18 +dimensional analysis,16 +anatomical directions,2 +supreme court of guam,1 +sentul kuala lumpur,2 +ducefixion,1 +red breasted merganser,4 +reservation,3 +in the land of blood and honey,9 +kate spade,2 +albina airstrip,1 +kankakee,1 +servicelink,2 +castilleja levisecta,1 +tonmeister,2 +chanda sahib,1 +lists of patriarchs archbishops and bishops,1 +mach zehnder modulator,1 +giants causeway,79 +literal,7 +uss gerald r ford,1 +monster hunter portable 3rd,3 +bayern munich v norwich city,1 +banking industry,1 +prankton united,1 +st elmo w acosta,1 +speech disorder,9 +welcome to my dna,1 +nouriel roubini,6 +arthur kill,2 +bill grundy,7 +jake gyllenhaal,1 +world bowl 2000,1 +wnt7a,1 +pink flamingo,2 +tridentine calendar,1 +ray ratto,1 +f 88 voodoo,1 +super star,4 +ondřej havelka,1 +sophia dorothea of celle,12 +clavulina tepurumenga,1 +vampire bats,4 +ihsan,1 +ocotea foetens,1 +gannett inc,1 +kemira,4 +gre–nal,2 +farm bureau mutual,1 +pete fox,1 +let him have it,3 +backwoods home magazine,6 +te reo maori remixes,1 +hussain andaryas,1 +bagun sumbrai,1 +the westin paris – vendôme,4 +xochiquetzal,4 +players tour championship 2013/2014,1 +picnic,7 +josh elliott,5 +ernak,3 +gracias,1 +k280ff,1 +bandaranaike–chelvanayakam pact,1 +patrick baert,1 +nausicaä of the valley of the wind,33 +al jurisich,1 +twitter,230 +window,38 +the power hour,1 +duplex worm,1 +sonam bajwa,16 +baljit singh deo,1 +indian jews,1 +outline of madagascar,1 +outback 8,1 +dye fig,1 +british columbia recall and initiative referendum 1991,1 +felipe suau,1 +north perry ohio,1 +gilbeys gin,1 +philippe cavoret,1 +luděk pachman,1 +the it girl,1 +dragonnades,1 +rick debruhl,2 +xpath 20,2 +sean mcnulty,1 +william moser,1 +international centre for the settlement of investment disputes,1 +mendes napoli,2 +canadian rugby championship,1 +battle of maidstone,2 +boulevard theatre,2 +snow sheep,3 +penalty corner,1 +michael ricketts,5 +crocodile,2 +job safety analysis,5 +duffy antigen,1 +counties of virginia,1 +a place to bury strangers,5 +socialist workers’ party of iran,1 +wlw t,1 +core autosport,1 +west francia,10 +karen kilgariff,2 +pacific tsunami museum,1 +first avenue,1 +troubadour,1 +great podil fire,1 +chilean presidential referendum 1988,1 +pavol schmidt,1 +handguard,1 +crime without passion,1 +dio at donington uk live 1983 & 1987,1 +optic nerves,1 +wake forest school of medicine,1 +new jersey jewish news,2 +luke boden,2 +chris hicky,1 +beforu,2 +verch,1 +st roch,3 +civitas,1 +tmrevolution,3 +jamie spencer,1 +bond beam,1 +megan fox,4 +battle of bayan,1 +japan airlines flight 472,1 +yuen kay san,1 +the friendly ghost,1 +rice,14 +jack dellal,16 +lee ranaldo,9 +the overlanders,1 +earl castle stewart,5 +first down,1 +rheum maximowiczii,1 +washington state republican party,2 +ostwald bas rhin,1 +tennessee open,1 +kenneth kister,1 +ted kennedy,72 +preben elkjaer,1 +india reynolds,2 +santagata de goti,1 +henrietta churchill 2nd duchess of marlborough,1 +creteil,1 +ntt data,3 +zoot allures,4 +theatre of ancient greece,29 +bujinkan,6 +clube ferroviário da huíla,2 +nhn,4 +hp series 80,2 +interstate 15,4 +moszczanka,1 +lawnside school district,1 +virunga mountains,5 +hallway,1 +serb peoples radical party,1 +free dance,1 +mishawaka amphitheatre,1 +deerhead kansas,1 +utopiayile rajavu,1 +john w olver transit center,1 +futa tooro,1 +digoxigenin,5 +thomas schirrmacher,1 +twipra kingdom,1 +pulpwood,6 +think blue linux,1 +raho city taxi,1 +frederic remington art museum,1 +wajdi mouawad,1 +semi automatic firearm,12 +phyllis chase,1 +malden new york,1 +the aetiology of hysteria,2 +my maserati does 185,1 +friedrich wilhelm von jagow,1 +apne rang hazaar,1 +bór greater poland voivodeship,1 +india rubber,2 +bring your daughter to the slaughter,4 +yasser radwan,1 +kuala ketil,1 +notre dame de paris,1 +yuanjiang,1 +fengjuan,1 +tockenham,1 +transnistrian presidential election 1991,1 +gautami,28 +providenciales airport,1 +donald chumley,1 +middle finger,8 +calke abbey,4 +thou shalt not kill,1 +trail,7 +battle of dunkirk,43 +eyre yorke block,3 +mactan,3 +american ninja warrior,2 +nevel papperman,1 +ninja storm power rangers,1 +uss castle rock,1 +turcos,1 +philippine sea frontier,1 +irom chanu sharmila,7 +for the first time,2 +stian ringstad,1 +tréon,1 +hiro fujikake,1 +renewable energy in norway,4 +dedh ishqiya,18 +leucothoe,2 +ecmo,2 +knfm,1 +gangnam gu,1 +oadby town fc,1 +clamperl,2 +mummy cave,2 +kenneth d bailey,2 +peter freuchen,2 +dayanand bandodkar,2 +shawn crahan,16 +barbara trentham,2 +university of virginia school of nursing,1 +vöckla,1 +intuitive surgical inc,1 +cyncoed,4 +john l stevens,1 +daniel farabello,1 +trent harmon,5 +feroze gandhi unchahar thermal power station,1 +samuel powell,1 +pan slavic,1 +swimming at the 1992 summer olympics – womens 4 × 100 metre freestyle relay,1 +human behaviour,2 +siege of port royal,3 +eridug,1 +lafee,1 +north bethesda trail,1 +scheveningen system,1 +special penn thing,1 +pserimos,1 +pravda vítězí,1 +wiki dankowska,1 +transcript,13 +second inauguration of grover cleveland,1 +spent fuel,1 +ertms regional,2 +frederick scherger,1 +nivis,1 +herbert hugo menges,1 +kapitan sino,1 +samson,34 +minae mizumura,2 +gro kvinlog,1 +chasing shadows,2 +d j fontana,1 +massively multiplayer online game,27 +capture of new orleans,8 +meat puppet,1 +american pet products manufacturers association,3 +villardonnel,1 +sessile serrated adenoma,3 +patch products,1 +lodovico altieri,1 +portal,2 +jake maskall,4 +the shops at la cantera,8 +stage struck,5 +elizabeth m tamposi,2 +taylor swift,22 +forum spam,9 +barry cowdrill,3 +patagopteryx,2 +korg ms 2000,1 +hmas dubbo,2 +ss khaplang,2 +kevin kelly,1 +punk goes pop volume 5,3 +spurt,2 +bristol pound,5 +military history of finland during world war ii,10 +laguardia,1 +josé marcó del pont,1 +conditional expectation,18 +the beat goes on,1 +patricia buckley ebrey,1 +ali ibn yusuf,2 +caristii,1 +william l brandon,1 +fomite,5 +barcelona el prat airport,7 +mattequartier,4 +invading the sacred,1 +jefferson station,3 +chibalo,1 +phil voyles,1 +ramen,41 +archbishopric of athens,1 +robert arnot,1 +diethylhydroxylamine,2 +christian vazquez,1 +servage hosting,1 +ufo alien invasion,1 +blackburn railway station,3 +performance metric,19 +pencilings,1 +phosphoenolpyruvate,1 +under lights,2 +diego de la hoya,1 +felipe caicedo,5 +jimmy arguello,1 +cielo dalcamo,1 +jan navrátil,1 +linear pottery culture,9 +wbga,1 +k36dd,1 +die hard 2,22 +companding,8 +this is the modern world,10 +cosmology,26 +craig borten,1 +red pelicans,1 +ac gilbert,2 +fougasse,1 +leonardos robot,4 +john of whithorn,2 +david prescott barrows,2 +http cookie,168 +emilia telese,6 +herăstrău park,2 +lauro villar,1 +earl of lincoln,1 +born again,2 +milan rufus,1 +weper,2 +levitt bernstein,1 +jean de thevenot,1 +jill paton walsh,2 +leudal,1 +kyle mccafferty,1 +pluralistic walkthrough,2 +greetings to the new brunette,3 +angus maccoll,1 +loco live,2 +palm i705,1 +saila laakkonen,1 +ssta,1 +buch,1 +eduardo cunha,7 +marie bouliard,1 +mystic society,2 +chu jus house,1 +boob tube,8 +il mestiere della vita,1 +hadley fraser,7 +marek larwood,2 +imperial knight,2 +adbc,1 +houdini,8 +patrice talon,3 +iodamoeba,1 +long march,26 +nyinba,1 +maurice dunkley,1 +new south wales state election 1874–75,1 +john lee carroll,1 +poya bridge,1 +category talk military units and formations established in 2004,1 +the family values tour 1999,2 +brødrene hartmann,1 +miomelon,1 +john moran bailey,1 +san juan archipelago,1 +come as you are,7 +hypo niederösterreich,1 +saturn vi,2 +cherokee county kansas,1 +maher abu remeleh,1 +file talk jb grace singlejpg,1 +count paris,8 +template talk anime and manga,1 +kntv,4 +ganges river dolphin,4 +jerry pacht,1 +rapid response,1 +crunch bandicoot,1 +big gay love,2 +john mckay,1 +bareq,1 +nikon d2x,1 +intercontinental paris le grand hotel,1 +oakland alternative high school,1 +ekow eshun,1 +jimmy fortune,1 +american gladiator,2 +ella sophia armitage,1 +united we stand what more can i give,5 +maruti suzuki celerio,1 +geraldo rivera/trackback/,1 +dogs tobramycin contain a primary amine,1 +hot coffee mod,11 +shriners,25 +mora missouri,1 +seattle wa,1 +all star baseball 2003,1 +comparison of android e book reader software,7 +calling out loud,2 +initiative 912,1 +charles batchelor,2 +terry spraggan,2 +wallace thurman,2 +stefan smith,2 +george holding,22 +institute of business administration sukkar,1 +staten island new york,4 +valency,1 +chintamani taluk,1 +mahatma gandhi,1 +co orbital,1 +epex spot,1 +theodoric the great,3 +fk novi pazar,1 +zappas olympics,2 +gustav krupp von bohlen und halbach,1 +yasmany tomás,4 +notre temps,1 +cats %,1 +intramolecular vibrational energy redistribution,1 +graduate management admission test,49 +robin fleming,1 +daniel gadzhev,1 +achaean league,7 +the four books,1 +tunica people,1 +murray hurst,1 +hajipur,7 +wolfgang fischer,1 +bethel minnesota,2 +wincdemu,1 +aleksandar luković,5 +zilog,6 +will to live,1 +pgc,1 +captain sky,1 +eprobemide,1 +gunther plüschow,1 +jackson laboratory,3 +ss orontes,2 +bishop morlino,1 +eldorado air force station,2 +tin oxide,1 +john bell,2 +ajay banga,2 +nail polish remover induced contact dermatitis,1 +quinctia,1 +a/n urm 25d signal generator,1 +the art company,3 +seawind 300c,1 +half and half,7 +constantia czirenberg,1 +halifax county north carolina,4 +tunica vaginalis,9 +life & times of michael k,2 +methyl propionate,1 +carla bley band,1 +us secret service,2 +maría elena moyano,2 +lory meagher cup,9 +malay sultanate,1 +third lanark,1 +olivier dacourt,10 +angri,2 +ukrainian catholic eparchy of saints peter and paul,1 +phosphinooxazolines,1 +allied health professions,24 +hydroxybenzoic acid,1 +srinatha,3 +zone melting,5 +miko,1 +robert b downs,1 +resource management,3 +new year tree,1 +agraw imazighen,1 +catmando,8 +python ide,5 +rocky mount wilson roanoke rapids nc combined statistical area,1 +spanish crown,3 +ianis zicu,1 +william c hubbard,2 +islamic marital jurisprudence,5 +the school of night,1 +krdc,4 +el centro imperials,1 +atiq uz zaman,1 +sliba zkha,1 +file no mosquesvg,8 +herzegovinians,1 +paradise lost,1 +the fairly oddparents,6 +civic alliance,1 +anbu,3 +broadcaster,2 +le bon,1 +columbus nebraska,4 +inuit people,1 +the menace,6 +ilya ilyich mechnikov,1 +algonquin college,4 +seat córdoba wrc,1 +european route e30,6 +three lakes florida,1 +k10de,1 +glyphonyx rhopalacanthus,1 +ask rhod gilbert,1 +bolas criollas,1 +county borough of southport,1 +roll on mississippi,1 +pulitzer prize for photography,7 +mark fisher,1 +oakley g kelly,1 +tajikistani presidential election 1999,1 +the relapse,4 +nabil bentaleb,8 +apprentice,1 +dale brown,3 +studebaker packard hawk series,1 +yu gi oh trading card game,14 +paralimni,2 +institut national polytechnique de toulouse,1 +to catch a spy,1 +hammer,4 +mount judi,2 +thomas posey,1 +maxime baca,1 +arthur susskind,1 +elkins constructors,2 +siege of gaeta,1 +pemex,1 +henry o flipper award,1 +mccordsville indiana,1 +carife,1 +prima donna,1 +proton,1 +henry farrell,1 +randall davidson,1 +history of georgia,11 +beef tongue,4 +ted spread,4 +douglas xt 30,3 +heavenly mother,1 +monte santangelo,1 +lothar matthaus,1 +american party,2 +tire kingdom,1 +bastrop state park,3 +james maurice gavin,1 +blue bird all american,4 +time and a word,10 +runny babbit,1 +nordic regional airlines,6 +advanced scientifics,2 +the space traders,2 +mongol invasion of anatolia,1 +abu hayyan al gharnati,1 +lisa geoghan,3 +valentia harbour railway station,1 +silo,10 +jimmy zhingchak,1 +glamma kid,1 +bonneville high school,1 +secant line,5 +the longshots,2 +costa rican general election 1917,1 +an emotion away,1 +rawlins high school,1 +cold inflation pressure,4 +receptionthe,2 +tom payne,8 +tb treatment,1 +hatikvah,8 +ol yellow eyes is back,1 +vincent mroz,1 +travis bickle,1 +qatar stars league 1985–86,1 +electronic document management,1 +orliska,1 +gáspár orbán,1 +sunabeda,1 +donatus magnus,1 +lawrence e spivak,2 +cavalieri,1 +aw kuchler,1 +coat of arms of kuwait,1 +wallis–zieff–goldblatt syndrome,1 +doug heffernan,3 +g3 battlecruiser,3 +imran abbas,1 +plymouth,1 +gould colorado,1 +in japan,1 +delmar watson,1 +skygusty west virginia,1 +vesque sisters,1 +rushton triangular lodge,1 +italic font,3 +warner w hodgdon carolina 500,1 +blackamoors,5 +magna cum laude,14 +follow that horse,1 +jean snella,1 +chris frith,1 +soul power,2 +spare me the details,1 +ymer xhaferi,1 +murano glass,5 +michel magras,1 +rashard and wallace go to white castle,1 +venus figurines of malta,1 +didnt we almost have it all,1 +ew,1 +david h koch institute for integrative cancer research,2 +black coyote,1 +priob,2 +piera coppola,1 +budhism,4 +south african class h1 4 8 2t,1 +dimitris papamichael+dimitris+papamixail,3 +system sensor,1 +farragut class destroyer,1 +no down payment,1 +william rogers,1 +desperate choices to save my child,1 +joe launchbury,7 +queen seondeok of silla,11 +adams county wisconsin,1 +bandhan bank,1 +x ray tubes,1 +sporadic group,1 +lozovaya,1 +mairead maguire,3 +royal challengers bangalore in 2016,1 +janko of czarnków,1 +marosormenyes,1 +the deadly reclaim,1 +rick doblin,1 +gwen jorgensen,6 +shire of halls creek,1 +carlton house,6 +urad bean,1 +baton rouge louisiana,39 +kiel institute for the world economy,3 +the satuc cup,1 +harlem division,1 +argonaut,2 +choi jeongrye,2 +optical disc image,2 +groesbeek canadian war cemetery,2 +rangpur india,1 +android n,72 +tjeld class patrol boat,1 +together for yes,2 +tender dracula,1 +shane nelson,1 +palazzo ducale urbino,1 +angels,4 +double centralizer theorem,1 +homme,4 +world heart federation,1 +patricia ja lee,4 +a date with elvis,1 +saints row,1 +lanzhou lamian,1 +subcompact car,1 +jojo discography,5 +gary,18 +global returnable asset identifier,1 +aloysia weber,2 +emperor nero,2 +heavyweights,6 +hush records,1 +mewa textil service,2 +michigan gubernatorial election 1986,1 +solanine,9 +andré moritz,3 +foreign relations of china,12 +william t anderson,3 +lindquist field,1 +biggersdale hole,1 +manayunk/norristown line,1 +aliti,1 +budhivanta,3 +tm forum,4 +off plan property,1 +wu xin the monster killer,4 +aharon leib shteinman,1 +mark catano,1 +llanfihangel,1 +atp–adp translocase,4 +tótkomlós,1 +nikita magaloff,1 +xo telescope,1 +pseudomonas rhizosphaerae,1 +pccooler,1 +arcion therapeutics inc,8 +oklahoma gubernatorial election 2010,1 +seed treatment,3 +connecticut education network,1 +company85,1 +bryan molloy,1 +roupeiro,1 +wendt beach park,2 +entick v carrington,3 +firemens auxiliary,1 +shotcrete,14 +sepharial,1 +poet laureate of virginia,1 +musth,6 +dragon run state forest,3 +focal point,10 +pacific drilling,1 +intro,2 +priscus,1 +rokurō mochizuki,1 +bofur,2 +tiffany mount,1 +thanasis papazoglou,12 +life is grand,1 +ergersheim bas rhin,1 +medical reserve corps,3 +anthony ashley cooper 2nd earl of shaftesbury,1 +uefa euro 2012 group a,32 +america movil sab de cv,1 +christopher cook,1 +vladimir makanin,1 +file talk first battle of saratogausmaeduhistorygif,1 +dean foods,4 +logical thinking,1 +tychonic system,1 +hand washing,17 +bioresonance therapy,4 +günther burstyn,4 +religion in the united kingdom,35 +bancroft ontario,2 +alberta enterprise group,1 +belizean spanish,1 +minuscule 22,1 +hmga2,3 +sidama people,1 +shigeaki mori,2 +moonstars,1 +hazard,24 +chilis,6 +rango,3 +kenichi itō,1 +isle of rum,1 +shortwood united fc,1 +bronx gangs,1 +heterometaboly,2 +beagling,4 +jurgen pommerenke,1 +rockin,1 +st maria maggiore,1 +philipp reis,1 +timeboxing,12 +template talk tallahassee radio,1 +aarti puri,2 +john paul verree,2 +adam tomkins,1 +knoppers,1 +sven olov eriksson,1 +ruth bowyer,1 +höfðatorg tower 1,1 +citywire,3 +helen bosanquet,1 +ulex europaeus,4 +richard martyn,1 +hana sugisaki,2 +its all over now baby blue,6 +the myths and legends of king arthur and the knights of the round table,2 +dooce,1 +german submarine u 9,1 +george shearing,4 +bishop of winchester,3 +maximilian karl lamoral odonnell,2 +hec edmundson,1 +morgawr,3 +sovereign state,67 +avignon—la mitis—matane—matapédia,1 +duramax v8 engine,12 +villa rustica,2 +carl dorsey,1 +clairol,6 +abruzzo,22 +momsen lung,10 +m23 rebellion,2 +kira oreilly,1 +constitutive relation,2 +bifrontal craniotomy,1 +basilica of st nicholas amsterdam,2 +marinus kraus,1 +moog prodigy,2 +lucy hale,49 +lingiya,1 +idiopathic orbital inflammatory disease,3 +shaanxi youser group,1 +apeirohedron,1 +program of all inclusive care for the elderly,2 +tv3 ghana,3 +arnold schwarzenegger,338 +raquel carriedo tomás,1 +cincinnati playhouse in the park,2 +colobomata,2 +star craft 2,1 +yaaf,1 +fc santa clarita,1 +release me,3 +notts county supporters trust,1 +westchester airport,1 +slowhand at 70 – live at the royal albert hall,1 +bruce gray,2 +only the good die young,1 +sewell thomas stadium,1 +kyle cook,1 +northwest passage,1 +eurex airlines,1 +uss pierre,1 +feitsui dam,1 +sales force,1 +obrien class destroyer,5 +sant longowal institute of engineering and technology,3 +united states presidential election in oklahoma 1952,1 +edyta bartosiewicz,1 +marquess of dorset,1 +whiting wyoming,1 +akanda,1 +jim brewster,1 +mozdok republic of north ossetia alania,1 +maritime gendarmerie,2 +paresh patel,1 +communication art,1 +santa anita handicap,2 +dahlia,44 +qikpad,1 +pudhaiyal,3 +oroshi,1 +ioda,3 +willis j gertsch,1 +scurvy grass,1 +bombing of rotterdam,2 +gagarin russia,1 +dynamic apnea without fins,1 +loess,14 +hans adolf krebs,4 +poręby stare,1 +kismat ki baazi,1 +malcolm slesser,1 +blue crane route local municipality,1 +jean michel basquiat,104 +customs trade partnership against terrorism,3 +lower cove newfoundland and labrador,1 +aashiqui 2,6 +elliott lee,1 +edison electric light company,2 +i rigoberta menchú,1 +battle of tennōji,2 +transport workers union of america,1 +physical review b,1 +way too far,1 +breguet 941,1 +manuel hegen,1 +the blacklist,12 +john dorahy,4 +cinderella sanyu,1 +luis castañeda lossio,1 +headquarters of a military area,1 +jbala people,2 +petrofac emirates,1 +ins garuda,3 +australia national rugby league team,2 +state of emergency 2,3 +mexican sex comedy,2 +baby anikha,1 +notions,1 +android app //orgwikipedia/http/enmwikipediaorg/wiki/elasticity,1 +kissing you,2 +montearagón,1 +grzegorz proksa,3 +shook,1 +may hegglin anomaly,1 +chrysler rb engine,2 +gmcsf,2 +blacksburg,1 +chris hollod,1 +the new guy,1 +thulimbah queensland,1 +sust,1 +knight kadosh,2 +details,4 +nickel mining in new caledonia,3 +easter hotspot,1 +surinamese interior war,1 +field corn,2 +bolesław iii wrymouth,6 +lutwyche queensland,1 +michael campbell,1 +military ranks of turkey,3 +mícheal martin,1 +the architects dream,2 +joel robert,1 +thomas smith,1 +inclusion probability,1 +fucked company,1 +genderfluid,5 +lewisham by election 1891,1 +net promoter,98 +donald stewart,1 +xml base,2 +bhikhu parekh,4 +anthocharis cardamines,1 +vuosaari,1 +demographics of burundi,1 +dst,1 +david ensor,2 +mount pavlof,1 +vince young,5 +st beunos ignatian spirituality centre,4 +ezekiel 48,1 +lewis elliott chaze,1 +template talk croatia squad 2012 mens european water polo championship,1 +the voice of the philippines,4 +whites ferry,1 +cananga odorata,9 +man of steel,2 +john michael talbot,2 +superior oblique myokymia,2 +anisochilus,2 +e421,1 +midnight rider,14 +matrícula consular,1 +first nehru ministry,2 +christopher mcculloch,2 +ems chemie,12 +dominique martin,1 +university club of washington dc,1 +nurse education,5 +theyre coming to take me away ha haaa,1 +bill dauterive,4 +belhar,1 +heel and toe,4 +university of the arctic members,2 +mitava,1 +wjmx fm,1 +father callahan,4 +divine word academy of dagupan,1 +bogs,1 +denny heck,2 +church of st james valletta,1 +field cathedral of the polish army,1 +indian skimmer,1 +history of british airways,3 +international mobile subscriber identity,38 +suzel roche,1 +steven watt,1 +duke ellineton,1 +kirbys avalanche,4 diff --git a/tests/testdata/will_play_text.csv.bz2 b/tests/testdata/will_play_text.csv.bz2 Binary files differnew file mode 100755 index 0000000..e3bec9d --- /dev/null +++ b/tests/testdata/will_play_text.csv.bz2 @@ -1,7 +1,7 @@ [pytest] addopts = -s markers = - json: run only the redisjson module tests + redismod: run only the redis module tests [tox] minversion = 3.2.0 |