Skip to content

Commit f2be3cd

Browse files
committed
Added support for dynamic indices , close #2
1 parent c810b1e commit f2be3cd

File tree

5 files changed

+201
-90
lines changed

5 files changed

+201
-90
lines changed

README.md

Lines changed: 50 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,22 +15,10 @@ Elasticsearch in laravel as if it were native to Laravel, meaning:
1515
- [Migrations](#migrations)
1616
- ES features like [Geo Filtering](#geo) & [Regular Expressions](#regex-in-where)
1717

18-
- No need to write your own DSL queries ([unless you want to](#raw-dsl)!)
18+
- [Dynamic Indices](#dynamic-indies)
19+
- No need to write your own DSL queries ([unless you want to](#raw-dsl))
1920
- [Eloquent style searching](#elasticsearching)
2021

21-
> # Alpha release notice
22-
> This package is being released prematurely to an interested community of testers. It is not ready for production just yet only due to a lack of testing mileage. Once deemed stable, the plugin will move to V1. Elasticsearch is a deep topic on its own and there are many native features that have not yet been included.
23-
>
24-
> #### Versioning Schema: {plugin_version}.{laravel_version}.{iteration}
25-
>
26-
> ex: 0.8.1
27-
>
28-
> Version 0 will be alpha & beta
29-
> Version 1 will be RC & stable
30-
> Version 2+ will be next gen feature set
31-
32-
____
33-
3422
Installation
3523
===============
3624

@@ -632,7 +620,7 @@ Book::term('Eric')->search();
632620

633621
- To search across all the fields in the **books** index for: **eric OR (lean AND startup)**
634622
- ***Note**: You can't start a search query chain with and/or and you can't have subsequent chained terms without and/or
635-
- **ordering matters***
623+
- **ordering matters***
636624

637625
```php
638626
Book::term('Eric')->orTerm('Lean')->andTerm('Startup')->search();
@@ -1274,6 +1262,53 @@ Queues
12741262
_[Coming]_
12751263

12761264

1265+
Dynamic Indies
1266+
==============
1267+
In some cases you will need to split a model into different indices. There are limits to this to keep within reasonable
1268+
Laravel ORM bounds, but if you keep the index prefix consistent then the plugin can manage the rest.
1269+
1270+
For example, let's imagine we're tracking page hits, the `PageHit.php` model could be
1271+
1272+
```php
1273+
<?php
1274+
1275+
namespace App\Models;
1276+
1277+
use PDPhilip\Elasticsearch\Eloquent\Model as Eloquent;
1278+
1279+
class PageHit extends Eloquent
1280+
{
1281+
protected $connection = 'elasticsearch';
1282+
protected $index = 'page_hits_*'; //Dynamic index
1283+
1284+
}
1285+
```
1286+
1287+
If you set a dynamic index you can read/search across all the indices that match the prefix `page_hits_`
1288+
1289+
```php
1290+
$pageHits = PageHit::where('page_id',1)->get();
1291+
```
1292+
1293+
You will need to set the record's actual index when creating a new record, with `setIndex('value')`
1294+
1295+
Create example:
1296+
1297+
```php
1298+
$pageHit = new PageHit
1299+
$pageHit->page_id = 4;
1300+
$pageHit->ip = $someIp;
1301+
$pageHit->setIndex('page_hits_'.date('Y-m-d'));
1302+
$pageHit->save();
1303+
1304+
```
1305+
1306+
Each eloquent model will have the current record's index embedded into it, to retrieve it simply call `getRecordIndex()`
1307+
1308+
```php
1309+
$pageHit->getRecordIndex(); //returns page_hits_2021-01-01
1310+
```
1311+
12771312
RAW DSL
12781313
========
12791314

src/DSL/Bridge.php

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -119,18 +119,20 @@ public function processFind($wheres, $options, $columns): Results
119119
// }
120120
// }
121121
$params = $this->buildParams($this->index, $wheres, $options, $columns);
122-
return $this->_returnSearch($params,__FUNCTION__);
122+
123+
return $this->_returnSearch($params, __FUNCTION__);
123124

124125
}
125126

126-
public function processSearch($searchParams,$searchOptions,$wheres,$opts,$fields,$cols)
127+
public function processSearch($searchParams, $searchOptions, $wheres, $opts, $fields, $cols)
127128
{
128-
$params = $this->buildSearchParams($this->index, $searchParams, $searchOptions,$wheres,$opts,$fields,$cols);
129-
return $this->_returnSearch($params,__FUNCTION__);
129+
$params = $this->buildSearchParams($this->index, $searchParams, $searchOptions, $wheres, $opts, $fields, $cols);
130+
131+
return $this->_returnSearch($params, __FUNCTION__);
130132

131133
}
132134

133-
protected function _returnSearch($params,$source)
135+
protected function _returnSearch($params, $source)
134136
{
135137
if (empty($params['size'])) {
136138
$params['size'] = $this->maxSize;
@@ -151,7 +153,7 @@ public function processDistinct($column, $wheres): Results
151153
if (is_array($column)) {
152154
$col = $column[0];
153155
}
154-
$params = $this->buildParams($this->index,$wheres);
156+
$params = $this->buildParams($this->index, $wheres);
155157
$params['body']['aggs']['distinct_'.$col]['terms'] = [
156158
'field' => $col,
157159
'size' => $this->maxSize,
@@ -177,7 +179,7 @@ public function processDistinct($column, $wheres): Results
177179

178180
public function processShowQuery($wheres, $options, $columns)
179181
{
180-
$params = $this->buildParams($this->index,$wheres, $options, $columns);
182+
$params = $this->buildParams($this->index, $wheres, $options, $columns);
181183

182184
return $params['body']['query']['query_string']['query'] ?? null;
183185
}
@@ -194,7 +196,9 @@ public function processSave($data, $refresh): Results
194196
$id = $data['_id'];
195197
unset($data['_id']);
196198
}
197-
// $data = $this->cleanData($data);
199+
if (isset($data['_index'])) {
200+
unset($data['_index']);
201+
}
198202
$params = [
199203
'index' => $this->index,
200204
'body' => $data,
@@ -551,7 +555,7 @@ private function _minAggregate($wheres, $options, $columns): Results
551555

552556
private function _sumAggregate($wheres, $options, $columns): Results
553557
{
554-
$params = $this->buildParams($this->index,$wheres, $options);
558+
$params = $this->buildParams($this->index, $wheres, $options);
555559
try {
556560
$agg = new SumAggregation('sum_value', $columns[0]);
557561
$params['body']['aggs']['sum_value'] = $agg->toArray();
@@ -583,7 +587,7 @@ private function _avgAggregate($wheres, $options, $columns): Results
583587

584588
private function _matrixAggregate($wheres, $options, $columns): Results
585589
{
586-
$params = $this->buildParams($this->index,$wheres, $options);
590+
$params = $this->buildParams($this->index, $wheres, $options);
587591
try {
588592
$agg = new MatrixAggregation('sum_value', $columns);
589593
$params['body']['aggs']['statistics'] = $agg->toArray();
@@ -617,6 +621,7 @@ private function _sanitizeSearchResponse($response, $params, $queryTag)
617621
if (!empty($response['hits']['hits'])) {
618622
foreach ($response['hits']['hits'] as $hit) {
619623
$datum = [];
624+
$datum['_index'] = $hit['_index'];
620625
$datum['_id'] = $hit['_id'];
621626
if (!empty($hit['_source'])) {
622627
foreach ($hit['_source'] as $key => $value) {

src/DSL/QueryBuilder.php

Lines changed: 36 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -18,42 +18,42 @@ trait QueryBuilder
1818

1919
protected static $equivalenceOperators = ['in', 'nin'];
2020

21-
protected static $clauseOperators = ['ne', 'gt', 'gte', 'lt', 'lte', 'between', 'not_between', 'like', 'not_like', 'exists','regex'];
21+
protected static $clauseOperators = ['ne', 'gt', 'gte', 'lt', 'lte', 'between', 'not_between', 'like', 'not_like', 'exists', 'regex'];
2222

2323

2424
//======================================================================
2525
// Parameter builders
2626
//======================================================================
2727

28-
public static function buildSearchParams($index, $searchQuery, $searchOptions,$wheres = [],$options = [],$fields = [],$columns = [])
28+
public static function buildSearchParams($index, $searchQuery, $searchOptions, $wheres = [], $options = [], $fields = [], $columns = [])
2929
{
3030
$params = [];
31-
if ($index){
31+
if ($index) {
3232
$params['index'] = $index;
3333
}
3434
$params['body'] = [];
3535

3636

3737
$queryString['query'] = $searchQuery;
38-
if($wheres){
38+
if ($wheres) {
3939
$wheres = self::_buildQuery($wheres);
4040
$whereQueryString = $wheres['query']['query_string']['query'] ?? null;
41-
if ($whereQueryString){
41+
if ($whereQueryString) {
4242
$queryString['query'] = '('.$searchQuery.') AND '.$whereQueryString;
4343
}
4444
}
4545

46-
if ($fields){
46+
if ($fields) {
4747
$queryString['fields'] = [];
48-
foreach ($fields as $field => $boostLevel){
49-
if($boostLevel > 1){
48+
foreach ($fields as $field => $boostLevel) {
49+
if ($boostLevel > 1) {
5050
$field = $field.'^'.$boostLevel;
5151
}
5252
$queryString['fields'][] = $field;
5353
}
5454
}
55-
if ($searchOptions){
56-
foreach ($searchOptions as $searchOption => $searchOptionValue){
55+
if ($searchOptions) {
56+
foreach ($searchOptions as $searchOption => $searchOptionValue) {
5757
$queryString[$searchOption] = $searchOptionValue;
5858
}
5959
}
@@ -63,7 +63,7 @@ public static function buildSearchParams($index, $searchQuery, $searchOptions,$w
6363
if ($columns && $columns != '*') {
6464
$params['body']['_source'] = $columns;
6565
}
66-
if ($options){
66+
if ($options) {
6767
$opts = self::_buildOptions($options);
6868
if ($opts) {
6969
foreach ($opts as $key => $value) {
@@ -75,17 +75,18 @@ public static function buildSearchParams($index, $searchQuery, $searchOptions,$w
7575
}
7676
}
7777
}
78-
if (self::$filter){
78+
if (self::$filter) {
7979
$params = self::_parseFilterParameter($params, self::$filter);
8080
}
81+
8182
return $params;
8283
}
8384

8485
public static function buildParams($index, $wheres, $options = [], $columns = [], $_id = null)
8586
{
86-
if ($index){
87+
if ($index) {
8788
$params = [
88-
'index' => $index
89+
'index' => $index,
8990
];
9091
}
9192

@@ -108,7 +109,7 @@ public static function buildParams($index, $wheres, $options = [], $columns = []
108109
}
109110
}
110111
}
111-
if (self::$filter){
112+
if (self::$filter) {
112113
$params = self::_parseFilterParameter($params, self::$filter);
113114
}
114115

@@ -173,7 +174,7 @@ private static function _ninQueryString($key, $values): string
173174
private static function _parseParams($key, $value): string
174175
{
175176

176-
if ($key == 'and' || $key == 'or') {
177+
if ($key === 'and' || $key === 'or') {
177178
return self::{'_'.$key.'QueryString'}($value);
178179
}
179180
if (is_array($value)) {
@@ -301,8 +302,8 @@ private static function _buildOptions($options): array
301302
$return['body']['min_score'] = $value;
302303
break;
303304
case 'filters':
304-
foreach ($value as $filterType => $filerValues){
305-
self::_parseFilter($filterType,$filerValues);
305+
foreach ($value as $filterType => $filerValues) {
306+
self::_parseFilter($filterType, $filerValues);
306307
}
307308
break;
308309
case 'multiple':
@@ -318,22 +319,22 @@ private static function _buildOptions($options): array
318319
return $return;
319320
}
320321

321-
public static function _parseFilter($filterType,$filterPayload)
322+
public static function _parseFilter($filterType, $filterPayload)
322323
{
323-
switch ($filterType){
324+
switch ($filterType) {
324325
case 'filterGeoBox':
325326
self::$filter['filter']['geo_bounding_box'][$filterPayload['field']] = [
326-
'top_left' => $filterPayload['topLeft'],
327+
'top_left' => $filterPayload['topLeft'],
327328
'bottom_right' => $filterPayload['bottomRight'],
328329
];
329330
break;
330331
case 'filterGeoPoint':
331332
self::$filter['filter']['geo_distance'] = [
332-
'distance' => $filterPayload['distance'],
333+
'distance' => $filterPayload['distance'],
333334
$filterPayload['field'] => [
334335
'lat' => $filterPayload['geoPoint'][0],
335336
'lon' => $filterPayload['geoPoint'][1],
336-
]
337+
],
337338

338339
];
339340
break;
@@ -354,35 +355,36 @@ private static function _parseSortOrder($value): array
354355
return $sort->toArray();
355356
}
356357

357-
public static function _parseFilterParameter($params,$filer)
358+
public static function _parseFilterParameter($params, $filer)
358359
{
359360
$body = $params['body'];
360-
if (!empty($body['query']['match_all'])){
361+
if (!empty($body['query']['match_all'])) {
361362
$filteredBody = [
362363
'query' => [
363364
'bool' => [
364-
'must' => [
365+
'must' => [
365366
'match_all' => $body['query']['match_all'],
366367
],
367-
'filter' => $filer['filter']
368-
]
369-
]
368+
'filter' => $filer['filter'],
369+
],
370+
],
370371
];
371372
$params['body'] = $filteredBody;
372373
}
373-
if (!empty($body['query']['query_string'])){
374+
if (!empty($body['query']['query_string'])) {
374375
$filteredBody = [
375376
'query' => [
376377
'bool' => [
377-
'must' => [
378+
'must' => [
378379
'query_string' => $body['query']['query_string'],
379380
],
380-
'filter' => $filer['filter']
381-
]
382-
]
381+
'filter' => $filer['filter'],
382+
],
383+
],
383384
];
384385
$params['body'] = $filteredBody;
385386
}
387+
386388
return $params;
387389
}
388390
}

0 commit comments

Comments
 (0)