Skip to content

Commit 38cd862

Browse files
examples integration tests
1 parent 4b7e9fb commit 38cd862

35 files changed

+418
-63
lines changed

examples/alias_migration.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
will have index set to the concrete index whereas the class refers to the
3636
alias.
3737
"""
38-
import os
38+
import asyncio
3939
from datetime import datetime
4040
from fnmatch import fnmatch
4141

@@ -125,9 +125,9 @@ def migrate(move_data=True, update_alias=True):
125125
)
126126

127127

128-
if __name__ == "__main__":
128+
def main():
129129
# initiate the default connection to elasticsearch
130-
connections.create_connection(hosts=[os.environ["ELASTICSEARCH_URL"]])
130+
connections.create_connection(hosts=["http://localhost:9200"])
131131

132132
# create the empty index
133133
setup()
@@ -143,3 +143,10 @@ def migrate(move_data=True, update_alias=True):
143143

144144
# create new index
145145
migrate()
146+
147+
# close the connection
148+
connections.get_connection().close()
149+
150+
151+
if __name__ == "__main__":
152+
asyncio.run(main())

examples/async/parent_child.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -159,14 +159,14 @@ def search_answers(self):
159159
s = s.params(routing=self.meta.id)
160160
return s
161161

162-
def get_answers(self):
162+
async def get_answers(self):
163163
"""
164164
Get answers either from inner_hits already present or by searching
165165
elasticsearch.
166166
"""
167167
if "inner_hits" in self.meta and "answer" in self.meta.inner_hits:
168168
return self.meta.inner_hits.answer.hits
169-
return list(self.search_answers())
169+
return [a async for a in self.search_answers()]
170170

171171
async def save(self, **kwargs):
172172
self.question_answer = "question"
@@ -188,8 +188,7 @@ def _matches(cls, hit):
188188
def search(cls, **kwargs):
189189
return cls._index.search(**kwargs).exclude("term", question_answer="question")
190190

191-
@property
192-
async def question(self):
191+
async def get_question(self):
193192
# cache question in self.meta
194193
# any attributes set on self would be interpretted as fields
195194
if "question" not in self.meta:

examples/async/percolate.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@
2020

2121
from elasticsearch_dsl import (
2222
AsyncDocument,
23+
AsyncSearch,
2324
Keyword,
2425
Percolator,
2526
Q,
26-
Search,
2727
Text,
2828
async_connections,
2929
)
@@ -40,22 +40,22 @@ class BlogPost(AsyncDocument):
4040
class Index:
4141
name = "test-blogpost"
4242

43-
def add_tags(self):
43+
async def add_tags(self):
4444
# run a percolation to automatically tag the blog post.
45-
s = Search(index="test-percolator")
45+
s = AsyncSearch(index="test-percolator")
4646
s = s.query(
4747
"percolate", field="query", index=self._get_index(), document=self.to_dict()
4848
)
4949

5050
# collect all the tags from matched percolators
51-
for percolator in s:
51+
async for percolator in s:
5252
self.tags.extend(percolator.tags)
5353

5454
# make sure tags are unique
5555
self.tags = list(set(self.tags))
5656

5757
async def save(self, **kwargs):
58-
self.add_tags()
58+
await self.add_tags()
5959
return await super().save(**kwargs)
6060

6161

@@ -82,7 +82,7 @@ class Index:
8282
async def setup():
8383
# create the percolator index if it doesn't exist
8484
if not await PercolatorDoc._index.exists():
85-
PercolatorDoc.init()
85+
await PercolatorDoc.init()
8686

8787
# register a percolation query looking for documents about python
8888
await PercolatorDoc(

examples/completion.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
that does ascii folding.
2727
"""
2828

29+
import asyncio
2930
import os
3031
from itertools import permutations
3132

@@ -72,7 +73,7 @@ class Index:
7273
settings = {"number_of_shards": 1, "number_of_replicas": 0}
7374

7475

75-
if __name__ == "__main__":
76+
def main():
7677
# initiate the default connection to elasticsearch
7778
connections.create_connection(hosts=[os.environ["ELASTICSEARCH_URL"]])
7879

@@ -97,3 +98,10 @@ class Index:
9798
# print out all the options we got
9899
for option in response.suggest.auto_complete[0].options:
99100
print("%10s: %25s (%d)" % (text, option._source.name, option._score))
101+
102+
# close the connection
103+
connections.get_connection().close()
104+
105+
106+
if __name__ == "__main__":
107+
asyncio.run(main())

examples/composite_agg.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
# specific language governing permissions and limitations
1616
# under the License.
1717

18+
import asyncio
1819
import os
1920

2021
from elasticsearch_dsl import A, Search, connections
@@ -36,15 +37,16 @@ def run_search(**kwargs):
3637

3738
response = run_search()
3839
while response.aggregations.comp.buckets:
39-
yield from response.aggregations.comp.buckets
40+
for b in response.aggregations.comp.buckets:
41+
yield b
4042
if "after_key" in response.aggregations.comp:
4143
after = response.aggregations.comp.after_key
4244
else:
4345
after = response.aggregations.comp.buckets[-1].key
4446
response = run_search(after=after)
4547

4648

47-
if __name__ == "__main__":
49+
def main():
4850
# initiate the default connection to elasticsearch
4951
connections.create_connection(hosts=[os.environ["ELASTICSEARCH_URL"]])
5052

@@ -57,3 +59,10 @@ def run_search(**kwargs):
5759
"File %s has been modified %d times, first seen at %s."
5860
% (b.key.files, b.doc_count, b.first_seen.value_as_string)
5961
)
62+
63+
# close the connection
64+
connections.get_connection().close()
65+
66+
67+
if __name__ == "__main__":
68+
asyncio.run(main())

examples/parent_child.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
particular parent
4040
4141
"""
42+
import asyncio
4243
import os
4344
from datetime import datetime
4445

@@ -165,7 +166,7 @@ def get_answers(self):
165166
"""
166167
if "inner_hits" in self.meta and "answer" in self.meta.inner_hits:
167168
return self.meta.inner_hits.answer.hits
168-
return list(self.search_answers())
169+
return [a for a in self.search_answers()]
169170

170171
def save(self, **kwargs):
171172
self.question_answer = "question"
@@ -187,8 +188,7 @@ def _matches(cls, hit):
187188
def search(cls, **kwargs):
188189
return cls._index.search(**kwargs).exclude("term", question_answer="question")
189190

190-
@property
191-
def question(self):
191+
def get_question(self):
192192
# cache question in self.meta
193193
# any attributes set on self would be interpretted as fields
194194
if "question" not in self.meta:
@@ -209,7 +209,7 @@ def setup():
209209
index_template.save()
210210

211211

212-
if __name__ == "__main__":
212+
def main():
213213
# initiate the default connection to elasticsearch
214214
connections.create_connection(hosts=[os.environ["ELASTICSEARCH_URL"]])
215215

@@ -244,3 +244,12 @@ def setup():
244244
)
245245
question.save()
246246
answer = question.add_answer(honza, "Just use `elasticsearch-py`!")
247+
248+
# close the connection
249+
connections.get_connection().close()
250+
251+
return answer
252+
253+
254+
if __name__ == "__main__":
255+
asyncio.run(main())

examples/percolate.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
# specific language governing permissions and limitations
1616
# under the License.
1717

18+
import asyncio
1819
import os
1920

2021
from elasticsearch_dsl import (
@@ -91,8 +92,15 @@ def setup():
9192
).save(refresh=True)
9293

9394

94-
if __name__ == "__main__":
95+
def main():
9596
# initiate the default connection to elasticsearch
9697
connections.create_connection(hosts=[os.environ["ELASTICSEARCH_URL"]])
9798

9899
setup()
100+
101+
# close the connection
102+
connections.get_connection().close()
103+
104+
105+
if __name__ == "__main__":
106+
asyncio.run(main())
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Licensed to Elasticsearch B.V. under one or more contributor
2+
# license agreements. See the NOTICE file distributed with
3+
# this work for additional information regarding copyright
4+
# ownership. Elasticsearch B.V. licenses this file to you under
5+
# the Apache License, Version 2.0 (the "License"); you may
6+
# not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../../../examples/async/alias_migration.py
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../../../examples/async/completion.py
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../../../examples/async/composite_agg.py
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../../../examples/async/parent_child.py
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../../../examples/async/percolate.py
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# Licensed to Elasticsearch B.V. under one or more contributor
2+
# license agreements. See the NOTICE file distributed with
3+
# this work for additional information regarding copyright
4+
# ownership. Elasticsearch B.V. licenses this file to you under
5+
# the Apache License, Version 2.0 (the "License"); you may
6+
# not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
18+
from . import alias_migration
19+
from .alias_migration import ALIAS, PATTERN, BlogPost, migrate
20+
21+
22+
async def test_alias_migration(async_write_client):
23+
# create the index
24+
await alias_migration.setup()
25+
26+
# verify that template, index, and alias has been set up
27+
assert await async_write_client.indices.exists_template(name=ALIAS)
28+
assert await async_write_client.indices.exists(index=PATTERN)
29+
assert await async_write_client.indices.exists_alias(name=ALIAS)
30+
31+
indices = await async_write_client.indices.get(index=PATTERN)
32+
assert len(indices) == 1
33+
index_name, _ = indices.popitem()
34+
35+
# which means we can now save a document
36+
with open(__file__) as f:
37+
bp = BlogPost(
38+
_id=0,
39+
title="Hello World!",
40+
tags=["testing", "dummy"],
41+
content=f.read(),
42+
)
43+
await bp.save(refresh=True)
44+
45+
assert await BlogPost.search().count() == 1
46+
47+
# _matches work which means we get BlogPost instance
48+
bp = (await BlogPost.search().execute())[0]
49+
assert isinstance(bp, BlogPost)
50+
assert not bp.is_published()
51+
assert "0" == bp.meta.id
52+
53+
# create new index
54+
await migrate()
55+
56+
indices = await async_write_client.indices.get(index=PATTERN)
57+
assert 2 == len(indices)
58+
alias = await async_write_client.indices.get(index=ALIAS)
59+
assert 1 == len(alias)
60+
assert index_name not in alias
61+
62+
# data has been moved properly
63+
assert await BlogPost.search().count() == 1
64+
65+
# _matches work which means we get BlogPost instance
66+
bp = (await BlogPost.search().execute())[0]
67+
assert isinstance(bp, BlogPost)
68+
assert "0" == bp.meta.id
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Licensed to Elasticsearch B.V. under one or more contributor
2+
# license agreements. See the NOTICE file distributed with
3+
# this work for additional information regarding copyright
4+
# ownership. Elasticsearch B.V. licenses this file to you under
5+
# the Apache License, Version 2.0 (the "License"); you may
6+
# not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
18+
19+
from .completion import Person
20+
21+
22+
async def test_person_suggests_on_all_variants_of_name(async_write_client):
23+
await Person.init(using=async_write_client)
24+
25+
await Person(name="Honza Král", popularity=42).save(refresh=True)
26+
27+
s = Person.search().suggest("t", "kra", completion={"field": "suggest"})
28+
response = await s.execute()
29+
30+
opts = response.suggest.t[0].options
31+
32+
assert 1 == len(opts)
33+
assert opts[0]._score == 42
34+
assert opts[0]._source.name == "Honza Král"

0 commit comments

Comments
 (0)