Skip to content

Commit

Permalink
updated guide (#60)
Browse files Browse the repository at this point in the history
  • Loading branch information
devypt authored and beowulfenator committed Apr 30, 2016
1 parent 8a7a40e commit daeafca
Show file tree
Hide file tree
Showing 4 changed files with 148 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -6,6 +6,7 @@ Yii Framework 2 elasticsearch extension Change Log

- Bug: Updated debug panel classes to be consistent with yii 2.0.7 (beowulfenator)
- Enh #15: Special data provider `yii\elasticsearch\ActiveDataProvider` created (klimov-paul)
- Enh #60: Minor updates to guide (devypt, beowulfenator)


2.0.4 March 17, 2016
Expand Down
2 changes: 1 addition & 1 deletion docs/guide/README.md
Expand Up @@ -12,7 +12,7 @@ Getting Started

Usage
-----

* [Data Mapping & Indexing](mapping-indexing.md)
* [Using the Query](usage-query.md)
* [Using the ActiveRecord](usage-ar.md)
* [Working with data providers](usage-data-providers.md)
Expand Down
76 changes: 76 additions & 0 deletions docs/guide/mapping-indexing.md
@@ -0,0 +1,76 @@
Mapping & Indexing
==================

## Creating index and mapping

Since it is not always possible to update ElasticSearch mappings incrementally, it is a good idea to create several static methods in your model that deal with index creation and updates. Here is one example of how this can be done.

```php
Class Book extends yii\elasticsearch\ActiveRecord
{
// Other class attributes and methods go here
// ...

/**
* @return array This model's mapping
*/
public static function mapping()
{
return [
static::type() => [
'properties' => [
'name' => ['type' => 'string'],
'author_name' => ['type' => 'string'],
'publisher_name' => ['type' => 'string'],
'created_at' => ['type' => 'long'],
'updated_at' => ['type' => 'long'],
'status' => ['type' => 'long'],
]
],
];
}

/**
* Set (update) mappings for this model
*/
public static function updateMapping()
{
$db = static::getDb();
$command = $db->createCommand();
$command->setMapping(static::index(), static::type(), static::mapping());
}

/**
* Create this model's index
*/
public static function createIndex()
{
$db = static::getDb();
$command = $db->createCommand();
$command->createIndex(static::index(), [
'settings' => [ /* ... */ ],
'mappings' => static::mapping(),
//'warmers' => [ /* ... */ ],
//'aliases' => [ /* ... */ ],
//'creation_date' => '...'
]);
}

/**
* Delete this model's index
*/
public static function deleteIndex()
{
$db = static::getDb();
$command = $db->createCommand();
$command->deleteIndex(static::index(), static::type());
}
}
```

To create the index with proper mappings, call `Book::createIndex()`. If you have changed the mapping in a way that allows mapping update (e.g. created a new property), call `Book::updateMapping()`.

However, if you have changed a property (e.g. went from `string` to `date`), ElasticSearch will not be able to update the mapping. In this case you need to delete your index (by calling `Book::deleteIndex()`), create it anew with updated mapping (by calling `Book::createIndex()`), and then repopulate it with data.

## Indexing
TBD
71 changes: 70 additions & 1 deletion docs/guide/usage-ar.md
Expand Up @@ -107,4 +107,73 @@ $query->addStatisticalFacet('click_stats', ['field' => 'visit_count']);
$query->search(); // gives you all the records + stats about the visit_count field. e.g. mean, sum, min, max etc...
```

And there is so much more in it. "it’s endless what you can build"[?](https://www.elastic.co/)
## Complex queries

Any query can be composed using ElasticSearch's query DSL and passed to the `ActiveRecord::query()` method. However, ES query DSL is notorious for its verbosity, and these oversized queries soon become unmanageable.
Here is a method to make queries more maintainable. Start by defining a query class just as it is done for SQL-based `ActiveRecord`.

```php
class CustomerQuery extends ActiveQuery
{
public static function name($name)
{
return ['match' => ['name' => $name]];
}

public static function address($address)
{
return ['match' => ['address' => $address]];
}

public static function dateRange($dateFrom, $dateTo)
{
return ['range' => ['registration_date' => [
'gte' => $dateFrom,
'lte' => $dateTo,
]]];
}
}

```

Now you can use these query components to assemble the resulting query and/or filter.

```php
$customers = Customer::find()->filter([
CustomerQuery::registrationDateRange('2016-01-01', '2016-01-20'),
])->query([
'bool' => [
'should' => [
CustomerQuery::name('John'),
CustomerQuery::address('London'),
],
'must_not' => [
CustomerQuery::name('Jack'),
],
],
])->all();
```

## Aggregation

[The aggregations framework](https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations.html) helps provide aggregated data based on a search query. It is based on simple building blocks called aggregations, that can be composed in order to build complex summaries of the data.

Using the previously defined `Customer` class, let's find out how many customers have registered each day. To do that we use the `terms` aggregation.


```php
$aggData = Customer::find()->addAggregation('customers_by_date', 'terms', [
'field' => 'registration_date',
'order' => ['_count' => 'desc'],
'size' => 10, //top 10 registration dates
])->search(null, ['search_type' => 'count']);

```

In this example we are specifically requesting aggregation results only. The following code further process the data.

```php
$customersByDate = ArrayHelper::map($aggData['aggregations']['customers_by_date']['buckets'], 'key', 'doc_count');
```

Now `$customersByDate` contains 10 dates that correspond to the the highest number of users registered.

0 comments on commit daeafca

Please sign in to comment.