You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: search/implement_elasticseach.md
+82
Original file line number
Diff line number
Diff line change
@@ -380,3 +380,85 @@ class SearchableMixin(object):
380
380
381
381
The latest version of Flask-sqlalchemy will return the error `sqlalchemy.exc.ArgumentError: The "whens" argument to case(), when referring to a sequence of items, is now passed as a series of positional elements, rather than as a list.` if a list is used.
382
382
383
+
To trigger changes from the SQLAlchemy database such as before and after a commit is made, we can define class methods for each.
384
+
385
+
```python
386
+
# app/models.py: Before and after commit
387
+
388
+
classSearchableMixin(object):
389
+
# ...
390
+
391
+
@classmethod
392
+
defbefore_commit(cls, session):
393
+
session._changes = {
394
+
'add': list(session.new),
395
+
'update': list(session.dirty),
396
+
'delete': list(session.deleted)
397
+
}
398
+
399
+
@classmethod
400
+
defafter_commit(cls, session):
401
+
for obj in session._changes['add']:
402
+
ifisinstance(obj, SearchableMixin):
403
+
add_to_index(obj.__tablename__, obj)
404
+
for obj in session._changes['update']:
405
+
ifisinstance(obj, SearchableMixin):
406
+
add_to_index(obj.__tablename__, obj)
407
+
for obj in session._changes['delete']:
408
+
ifisinstance(obj, SearchableMixin):
409
+
remove_from_index(obj.__tablename__, obj)
410
+
session._changes =None
411
+
```
412
+
413
+
Just before a session is committed, the `before_commit()` handler will allow us to check what object has been added, modified or deleted through `session.new`, `session.dirty` and `session.delete` respectively. These objects are not going to be available anymore after a commit is made. `session._changes` dictionary allows us to save the objects and have them survive a commit since we shall be using them to update the Elasticsearch index.
414
+
415
+
As soon as a session has been successfully committed, this is the proper time to make changes on the Elasticsearch side of things using `after_commit()`. We begin by iterating over what has been added, modified or deleted and make corresponding calls to the indexing functions in the `search` module for objects with `SearchableMixin`.
416
+
417
+
We can include a simple `reindex()` helper method that can allow us to refresh an index with all the data in the relational side. You may experience instances where you have to manually update the Elasticsearch index to ensure the latest changes are effected.
418
+
419
+
```python
420
+
classSearchabelMixin(object):
421
+
# ...
422
+
423
+
@classmethod
424
+
defreindex(cls):
425
+
for obj incls.query:
426
+
add_to_index(cls.__tablename__, obj)
427
+
```
428
+
429
+
Given that `reindex` is a class method, you can run `Model.reindex()` to update the Elasticsearh index. Finally, to ensure that SQLAlchemy listens to database changes events, we can call the function `db.event.listen()` from SQLAlchemy. This function serves to call `before_commit` and `after_commit` methods before and after each commit respectively.
To ensure that `SearchableMixin` is fully incorporated into a model, we can pass it as a class argument to the select model as follows:
442
+
443
+
```python
444
+
# app/models.py: Integrate SearchableMixin into a model
445
+
446
+
classPost(SearchableMixin, db.Model):
447
+
# ...
448
+
```
449
+
450
+
With this minor change to the `Post` model, we can maintain a full text-search for posts. Let us begin by initializing all the index from the posts currently in the database:
451
+
452
+
```python
453
+
>>> Post.reindex()
454
+
```
455
+
456
+
And to search, we can do:
457
+
458
+
```python
459
+
>>> query, total = Post.search('test the Japan', 1, 20)
460
+
>>> total
461
+
7
462
+
>>> query.all()
463
+
[Post: test comment, Post: Another one test for you, Post: Why the diss, Post: Japan the great country, Post: I am the greatest, Post: Two of the tests were not done well, Post: There has got to be the best way around it]
0 commit comments