Skip to content

Commit

Permalink
#1 - Update README.
Browse files Browse the repository at this point in the history
  • Loading branch information
laurentguilbert committed Jan 13, 2017
1 parent f691c23 commit fd5e827
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 265 deletions.
192 changes: 9 additions & 183 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,10 @@ Add `trampoline` to your `INSTALLED_APPS`.
Define the setting:
```python
TRAMPOLINE = {
'CONNECTIONS': {
'default': {'hosts': 'localhost:9200'},
# 'another_conn': {'hosts': 'localhost:9201'},
},
'INDICES': {
'index_name': {
'models': (
'app_name.models.ModelName',
),
}
},
'HOSTS': [
{'host': 'localhost'},
],
'MODELS': [],
'OPTIONS': {
'celery_queue': None,
'fail_silently': True,
Expand All @@ -42,17 +35,13 @@ TRAMPOLINE = {
}
```

### CONNECTIONS
### HOSTS

`localhost` is already set by default.

Mapping of the different ElasticSearch hosts used in your project.

### INDICES

`{}` by default.

Each key inside `INDICES` represents an index which itself defines a list of `models` to be indexed.
### MODELS

### OPTIONS

Expand Down Expand Up @@ -80,9 +69,9 @@ from trampoline.mixins import ESIndexableMixin

In order to make your model indexable you must make it inherit from `ESIndexableMixin` and implement a few things.

#### es_doc_type (required)
#### es_serializer (required)

Set the attribute `es_doc_type` with the corresponding `DocType` used to serialize your model.
#### get_es_doc_type_mapping (optional)

#### is_indexable (optional)

Expand All @@ -103,178 +92,15 @@ def get_indexable_queryset(cls):

Return the list of contents that should be indexed for this model using the command `es_create_documents()` defined bellow. Make sure you don't forget the `classmethod` decorator.

## DocType

Mapping between your models and documents can either be manual or automatic. The two strategies are mutually exclusive.

#### Manual mapping (default)

Implement the method `get_es_doc_mapping` on your model and manually create your mapping.

```python
# myapp/models.py

class MyModel(models.Model):

def get_es_doc_mapping(self):
doc_type = self.es_doc_type()
doc_type.foo = self.foo
doc_type.bar = self.bar
return doc_type
```

Return an instance of `es_doc_type` mapped with your current model instance.

#### Automatic mapping

Set `es_auto_doc_type_mapping` to `True` inside your model to enable automatic mapping.

This method will automatically copy values from your model to your doc type.

You can also override this behavior on a field by field basis by implementing a method named `prepare_{field}`.

```python
# myapp/doc_types.py

import elasticsearch_dsl

class MyDocType(elasticsearch_dsl.DocType):
simple_field = elasticsearch_dsl.String()
computed_field = elasticsearch_dsl.String()

def prepare_computed_field(self, obj):
# obj being an instance of your model.
return obj.field1 + obj.field2
```

## Management commands

All management commands accept the following arguments:
- **--help**: Display an help message and the available arguments for the command.
- **--dry-run**: Run the command in dry run mode without actually changing anything.
- **--verbosity**: 0 to 3 from least verbose to the most. Default to 1.

### es_create_index

Create a new index based on its definition inside `ES_SETTINGS`.

Arguments:
- **--index**: Name of the index as defined in the settings.
- **--target** *(optional)*: Name of the actual index created.

If **target** is not provided a unique name will be generated by appending the current timestamp to **index**.

### es_delete_index

Delete an index along with all the documents in it.

Arguments:
- **index**: Name of the index.
- **--yes** *(optional)*: Bypass the command line's verification.
### es_create_indices

### es_create_alias

Create an alias from one index name to the other.

Arguments:
- **--index**: Name of the index as defined in the settings.
- **--target**: Name of the actual index.

### es_delete_alias

Delete an alias from one index name to the other.

Arguments:
- **--index**: Name of the index as defined in the settings.
- **--target**: Name of the actual index.
- **--yes** *(optional)*: Bypass the command line's verification.

### es_create_documents

Create documents based on the method `get_indexable_queryset()` on the related models.

Arguments:
- **--index**: Name of the index as defined in the settings.
- **--target** *(optional)*: Name of the actual index.
- **--threads** *(optional)*: Number of threads to be used, defaults to 4.
- **--cleanup** *(optional)*: Delete stale documents from the index.

**target** defaults to **index** if not provided.

## Pagination

A `Search` response cannot be as easily paginated as a `QuerySet` due to various constraints.

The best way to paginate a response is to use the custom paginator and view mixin provided with Trampoline.

### ESPaginationMixin

```python
from trampoline.views import ESPaginationMixin
```

In order to paginate your view you must make it inherit from `ESPaginationMixin` and implement a few things.

#### page_size (optional)

Set `page_size` to the desired number of results per page (defaults to 10).

#### get_search (required)

```python
def get_search(self):
search = Search()
...
return search
```

Return the `Search` object from which the response must be paginated.

Your view's `context_data` will then contain a `page` object as described bellow.

### Page

```python
from trampoline.paginator import Page
```

#### has_other_pages

Whether this is the last page of results or not.

#### hits

Paginated search results.

#### number

Corresponding page number.

#### paginator

Link back to the paginator from which the page is generated.

#### response

Search response.

#### total_count

Total number of results for the search.

### ESSearchPaginator

```python
from trampoline.paginator import ESSearchPaginator
```

You can also use the paginator on itself and outside of `ESPaginationMixin` if you ever need it. See the example bellow:

```python
page_size = 10
page_number = 2
search = Search()
...
paginator = ESSearchPaginator(search, page_size)
page = paginator.get_page(page_number)
```
49 changes: 0 additions & 49 deletions tests/test_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,52 +96,3 @@ def test_es_create_alias(self):
target='foobar_target'
)
self.assertAliasExists(index='foobar_target', name='foobar')

def test_es_delete_alias(self):
# Index name required.
with self.assertRaises(SystemExit):
call_command(
'es_delete_alias',
target='foobar_target'
)

# Target name required.
with self.assertRaises(SystemExit):
call_command(
'es_delete_alias',
index='foobar'
)

# Index doesn't exist.
with self.assertRaises(SystemExit):
call_command(
'es_delete_alias',
index='foobar',
target='foobar_target',
yes=True
)

self.createIndex('foobar_target')

# Alias doesn't exist.
with self.assertRaises(SystemExit):
call_command(
'es_delete_alias',
index='foobar',
target='foobar_target',
yes=True
)

self.trampoline_config.es.indices.put_alias(
index='foobar_target',
name='foobar'
)
self.assertAliasExists(index='foobar_target', name='foobar')

call_command(
'es_delete_alias',
index='foobar',
target='foobar_target',
yes=True
)
self.assertAliasDoesntExist(index='foobar_target', name='foobar')
14 changes: 11 additions & 3 deletions tests/test_mixins.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,21 +81,29 @@ def test_es_index(self):
settings.TRAMPOLINE['OPTIONS']['fail_silently'] = True

def test_es_delete(self):
# Asynchronous call.
# Async call.
token = Token.objects.create(name='token')
self.assertDocExists(token)
token.es_delete()
self.assertDocDoesntExist(Token)

# Synchronous call.
# Sync call.
token = Token.objects.create(name='token')
self.assertDocExists(token)
token.es_delete(async=False)
self.assertDocDoesntExist(Token)

# Fail silently if document doesn't exist.
# Async soft fail if document doesn't exist.
token.es_delete()

# Sync soft fail.
token.es_delete(async=False)

# Async hard fail.
settings.TRAMPOLINE['OPTIONS']['fail_silently'] = False
token.es_delete(async=False)
settings.TRAMPOLINE['OPTIONS']['fail_silently'] = True

def test_save(self):
token = Token(name='token')

Expand Down
30 changes: 0 additions & 30 deletions trampoline/management/commands/es_delete_alias.py

This file was deleted.

0 comments on commit fd5e827

Please sign in to comment.