Giter Club home page Giter Club logo

algoliasearch-laravel's Introduction

[DEPRECATED] Algolia Search API Client for Laravel

Algolia Search is a hosted full-text, numerical, and faceted search engine capable of delivering realtime results from the first keystroke.


This package is deprecated, we recommend you to use Laravel Scout. If you want to extend Scout capabilities, please refer to our dedicated documentation


Build Status Latest Version License

This PHP package integrates the Algolia Search API into the Laravel Eloquent ORM. It's based on the algoliasearch-client-php package.

Note: If you're using Laravel 4, checkout the algoliasearch-laravel-4 repository.

API Documentation

You can find the full reference on Algolia's website.

Table of Contents

  1. Install

  2. Quick Start

  3. Options

  4. Relationships

  5. Indexing

  6. Manage indices

  7. Eloquent compatibility

Install

Install via composer

Add algolia/algoliasearch-laravel to your composer.json file:

composer require algolia/algoliasearch-laravel

Service provider

Add the service provider to config/app.php in the providers array.

AlgoliaSearch\Laravel\AlgoliaServiceProvider::class

Publish vendor

Laravel Algolia requires a connection configuration. To get started, you'll need to publish all vendor assets:

php artisan vendor:publish

You can add the --provider="Vinkla\Algolia\AlgoliaServiceProvider" option to only publish assets of the Algolia package.

This will create a config/algolia.php file in your app that you can modify to set your configuration. Also, make sure you check for changes compared to the original config file after an upgrade.

Quick Start

Quick Start

The following code adds search capabilities to your Contact model creating a Contact index:

use Illuminate\Database\Eloquent\Model;
use AlgoliaSearch\Laravel\AlgoliaEloquentTrait;

class Contact extends Model
{
    use AlgoliaEloquentTrait;
}

By default all visible attributes are sent. If you want to send specific attributes you can do something like:

use Illuminate\Database\Eloquent\Model;

class Contact extends Model
{
    use AlgoliaEloquentTrait;

    public function getAlgoliaRecord()
    {
        return array_merge($this->toArray(), [
            'custom_name' => 'Custom Name'
        ]);
    }
}

After setting up your model, you need to manually do an initial import of your data. You can do this by calling reindex on your model class. Using our previous example, this would be:

Contact::reindex();

Ranking & Relevance

We provide many ways to configure your index settings to tune the overall relevancy, but the most important ones are the searchable attributes and the attributes reflecting the record popularity. You can configure them with the following code:

use Illuminate\Database\Eloquent\Model;

class Contact extends Model
{
    use AlgoliaEloquentTrait;

    public $algoliaSettings = [
        'searchableAttributes' => [
            'id',
            'name',
        ],
        'customRanking' => [
            'desc(popularity)',
            'asc(name)',
        ],
    ];
}

You can propagate (save) the settings to algolia by using the setSetting method:

Contact::setSettings();

Synonyms

Synonyms are used to tell the engine about words or expressions that should be considered equal in regard to the textual relevance.

Our synonyms API has been designed to manage as easily as possible a large set of synonyms for an index and its replicas.

You can use the synonyms API by adding a synonyms in $algoliaSettings class property like this:

use Illuminate\Database\Eloquent\Model;

class Contact extends Model
{
    use AlgoliaEloquentTrait;

    public $algoliaSettings = [
        'synonyms' => [
            [
                'objectID' => 'red-color',
                'type'     => 'synonym',
                'synonyms' => ['red', 'another red', 'yet another red']
            ]
        ]
    ];
}

You can propagate (save) the settings to algolia using the setSetting method:

Contact::setSettings();

Frontend Search (realtime experience)

Traditional search implementations tend to have search logic and functionality on the backend. This made sense when the search experience consisted of a user entering a search query, executing that search, and then being redirected to a search result page.

Implementing search on the backend is no longer necessary. In fact, in most cases it is harmful to performance because of the extra network and processing latency. We highly recommend the usage of our JavaScript API Client issuing all search requests directly from the end user's browser, mobile device, or client. It will reduce the overall search latency while offloading your servers at the same time.

In your JavaScript code you can do:

var client = algoliasearch('ApplicationID', 'Search-Only-API-Key');
var index = client.initIndex('YourIndexName');
index.search('something', function(success, hits) {
  console.log(success, hits)
}, { hitsPerPage: 10, page: 0 });

Backend Search

You could also use the search method, but it's not recommended to implement an instant/realtime search experience from the backend (having a frontend search gives a better user experience):

Contact::search('jon doe');

Options

Auto-indexing & Asynchronism

Each time a record is saved; it will be - asynchronously - indexed. On the other hand, each time a record is destroyed, it will be - asynchronously - removed from the index.

You can disable the auto-indexing and auto-removing by setting the following options:

use Illuminate\Database\Eloquent\Model;

class Contact extends Model
{
    use AlgoliaEloquentTrait;

    public static $autoIndex = false;
    public static $autoDelete = false;
}

You can temporarily disable auto-indexing. This is often done for performance reasons.

Contact::$autoIndex = false;
Contact::clearIndices();

for ($i = 0; $i < 10000; $i++) {
    $contact = Contact::firstOrCreate(['name' => 'Jean']);
}

Contact::reindex(); // Will use batch operations.
Contact::$autoIndex = true;

You can also make a dynamic condition for those two parameters by creating an autoIndex and/or autoDelete method on your model

use Illuminate\Database\Eloquent\Model;

class Contact extends Model
{
    use AlgoliaEloquentTrait;

    public function autoIndex()
    {
        if (\App::environment() === 'test') {
            return false;
        }

        return true;
    }

    public static autoDelete()
    {
        if (\App::environment() === 'test') {
            return false;
        }

        return true;
    }
}

Be careful to define those two methods in AlgoliaEloquentTrait. When putting those methods in a parent class they will be "erased" by AlgoliaEloquentTrait if used in a child class (because of php inheritance).

Custom Index Name

By default, the index name will be the pluralized class name, e.g. "Contacts". You can customize the index name by using the $indices option:

use Illuminate\Database\Eloquent\Model;

class Contact extends Model
{
    use AlgoliaEloquentTrait;

    public $indices = ['contact_all'];
}

Per-environment Indexes

You can suffix the index name with the current App environment using the following option:

use Illuminate\Database\Eloquent\Model;

class Contact extends Model
{
    use AlgoliaEloquentTrait;

    public static $perEnvironment = true; // Index name will be 'Contacts_{\App::environnement()}';
}

Custom objectID

By default, the objectID is based on your record's keyName (id by default). You can change this behavior specifying the objectIdKey option (be sure to use a uniq field).

use Illuminate\Database\Eloquent\Model;

class Contact extends Model
{
    use AlgoliaEloquentTrait;

    public static $objectIdKey = 'new_key';
}

Restrict Indexing to a Subset of Your Data

You can add constraints controlling if a record must be indexed by defining the indexOnly() method.

use Illuminate\Database\Eloquent\Model;

class Contact extends Model
{
    use AlgoliaEloquentTrait;

    public function indexOnly($index_name)
    {
        return (bool) $condition;
    }
}

Relationships

Relationships

By default the Algolia package will fetch the loaded relationships.

If you want to index records that haven't yet loaded any relations, you can do it by loading them in the getAlgoliaRecord that you can create in your model.

It will look like:

public function getAlgoliaRecord()
{
    /**
     * Load the categories relation so that it's available
     *  in the laravel toArray method
     */
    $this->categories;

   return $this->toArray();
}

In the resulted object, you will have categories converted to array by Laravel. If you want a custom relation structure you will instead do something like:

public function getAlgoliaRecord()
{
    /**
     * Load the categories relation so that it's available
     *  in the laravel toArray method
     */
    $extra_data = [];
    $extra_data['categories'] = array_map(function ($data) {
                                        return $data['name'];
                                }, $this->categories->toArray());

   return array_merge($this->toArray(), $extra_data);
}

Indexing

Visibility

By default, Algolia will only be able to access visible attributes of your model. So, for example, you will receive a No content in PUT request exception when using this example code, because invisible_attribute key returns an empty/null variable.

protected $visible = ['visible_attribute', 'other_visible_attribute'];

public function getAlgoliaRecord()
{
    return [
        'invisible_attribute' => $this->invisible_attribute
    ];
}

Before Indexing, be sure to have correctly listed your visible attributes. To bypass this safety mask imposed by Laravel, you may use $this->attributes['invisible_attribute'] to access directly to the attribute even if is not visible, but the recommendation is to avoid this type of access to attributes in your Model.

Manual Indexing

You can trigger indexing using the pushToIndex instance method.

$contact = Contact::firstOrCreate(['name' => 'Jean']);
$contact->pushToIndex();

Manual Removal

And trigger the removal using the removeFromIndex instance method.

$contact = Contact::firstOrCreate(['name' => 'Jean']);
$contact->removeFromIndex();

Reindexing

To safely reindex all your records (index to a temporary index + move the temporary index to the current one atomically), use the reindex class method:

Contact::reindex();

To reindex all your records (in place, without deleting outdated records):

Contact::reindex(false);

To set settings during the reindexing process:

Contact::reindex(true, true);

To keep settings that you set on the Algolia dashboard when reindexing and changing settings:

Contact::reindex(true, true, true);

To implement a callback that gets called everytime a batch of entities is indexed:

Contact::reindex(true, true, false, function ($entities)
{
    foreach ($entities as $entity)
    {
        var_dump($entity->id); // Contact::$id
    }
});

Clearing an Index

To clear an index, use the clearIndices class method:

Contact::clearIndices();

Manage indices

Primary/Replica

You can define replica indexes using the $algolia_settings variable:

use Illuminate\Database\Eloquent\Model;

class Contact extends Model
{
     use AlgoliaEloquentTrait;

     public $algoliaSettings = [
        'searchableAttributes' => [
            'id',
            'name',
        ],
        'customRanking' => [
            'desc(popularity)',
            'asc(name)',
        ],
        'replicas' => [
            'contacts_desc',
        ],
    ];

    public $replicasSettings = [
        'contacts_desc' => [
            'ranking' => [
                'desc(name)',
                'typo',
                'geo',
                'words',
                'proximity',
                'attribute',
                'exact',
                'custom'
            ]
        ]
    ];
}

To search using a replica, use the following code:

Book::search('foo bar', ['index' => 'contacts_desc']);

Target Multiple Indexes

You can index a record in several indexes using the $indices property:

use Illuminate\Database\Eloquent\Model;

class Contact extends Model
{
    use AlgoliaEloquentTrait;

    public $indices = [
        'contact_public',
        'contact_private',
    ];

    public function indexOnly($indexName)
    {
        if ($indexName == 'contact_public')
            return true;

        return $this->private;
    }

}

To search using an extra index, use the following code:

Book::search('foo bar', ['index' => 'contacts_private']);

Eloquent compatibility

Eloquent compatibility

Doing:

Ad::where('id', $id)->update($attributes);

will not trigger anything in the model (so no update will happen in Algolia). This is because it is not an Eloquent call. It is just a convenient way to generate the query hidden behind the model.

To make this query work with Algolia you need to do it like this:

Ad::find($id)->update($attributes);

Compatibility

Compatible with 5.x applications

algoliasearch-laravel's People

Contributors

5outh avatar algoliareadmebot avatar bobylito avatar code-poel avatar codeharmonics avatar felixmalfait avatar freekmurze avatar ghostprofile avatar giampy5 avatar harrisbp avatar italobc avatar janpetr avatar joshforbes avatar julienbourdeau avatar matthijs110 avatar maxiloc avatar nikita240 avatar plnech avatar rayrutjes avatar redox avatar seafoox avatar speedblue avatar vinkla avatar wlkns avatar zyml avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

algoliasearch-laravel's Issues

Can you limit attributes (table columns) uploaded to Algolia?

For example, I may have 12 columns in my model/table, but I only want to upload 3 attibutes uploaded to Algolia?.
I understand I can set "searchable attributes" to limit which attributes are searched, but still all 12 attributes/table columns get uploaded to Alogolia.

You might want to sort the read me out...

The readme references Ruby and doesn't tell me how to search. The English is poor and so is the grammar,

As yet, I don't want to give Algolia my hard earned money or contemplate using this package in a Laravel app.

Disabling for Testing

Thank you all for your work on this package! It's much appreciated.

Is there a good way to disable the package when running tests? I'm migrating and seeding my database when I run my tests, and the package is attempting to push the data to Algolia every time a model is saved.

What do you think?

Date condition not working

Hi, This code works correctly in Laravel

Post::where('created_at', '>', $date)->get()

but happen error in Alogolia search

Post::search($request->search)->where('created_at', '>', $date)->get()

And error message:
AlgoliaSearch\AlgoliaException with message 'Invalid syntax for numeric condition:created_at=>'

Anyway Not To Index A Particular Record?

I am using getAlgoliaRecord() to create a custom structure in my model

I am wonder is there anyway I can break out of this function aka not index to algolia if for example a record is not public?

I tried

if ($status !== 'public' ) {
return null;
}

But the record still got pushed

indexOnly() indexname how to write

I was looking at this func

public function indexOnly($index_name)
{
        return (bool) $condition;
}

But how do i write $index_name?

is it

public function indexOnly("myIndexName")
{
return (bool) $condition;
}

or

public function indexOnly(['myIndexName'])
{
return (bool) $condition;
}

Also if I run save() on my model it will reindex.

But can I disable the index for a one time save only or must I use indexOnly() ?

Slaves set through setSetting do not take advantage of Per-environment Indexes option

Hello,

I was working on taking my granular build settings for our business out of being setup via the dashboard and configuring it all through my laravel models. However, I have discovered that the slaves feature does not take advantage of the Per-environment Indexes feature. I'm using the following format
MASTER_LOCAL
MASTER_PRODUCTION
local and production are added per the per-environment indexes feature. However if I add the following and setSettings:
'slaves' => [
'EXAMPLESLAVENAME',
],
For production and local they create an index just called EXAMPLESLAVENAME. I don't want to screw anything else on my production indexes after relinking my old dashboard created slave so I haven't tested if one overwrites the slave index created based on whoever ran setsettings last but based on it not prefixing the name im going to assume it does. If this is as intended could I request it as a feature to be added or at least a $slavePerEnvironment flag to do so ? That would be greatly appreciated!!

Hosts unreachable: Resolving timed out after 2000 milliseconds

Hi,

I´m running into this error with Laravel 5.1 when trying to index some data. Always get this error:
AlgoliaException in Client.php line 392:

Hosts unreachable: Resolving timed out after 2000 milliseconds,Resolving timed out after 2000 milliseconds,Resolving timed out after 4000 milliseconds,Resolving timed out after 4000 milliseconds

Found something similar on Twitter from 2013 but can´t figure out how to solve my problem.

Any Ideas on that ?
Thanks
Marc

Fail to reindex an index with slave

Getting exception when calling reindex():

[AlgoliaSearch\AlgoliaException]
A slave index is already slave of another index

It appear to be calling setSettings() before unsetting the "slaves" key

        if (count(array_keys($settings)) > 0) {
            $index->setSettings($settings);
        }

        if ($b && isset($settings['slaves'])) {
            $b = false;
            unset($settings['slaves']);
        }

Please review this issue.

Several bugs setting up the index

Hi,

I've the following:

public $algoliaSettings = [
            'attributesToIndex' => [
                'title', 'categories.name', 'company.name',
                    'company.description', 'location.name'
            ],
            'customRanking' => [
                'desc(featured)',
                'desc(created_at)',
            ],
            'slaves' => [
                'jobs_home',
            ],
        ];

    public $slavesSettings = [
        'jobs_home' => [
            'ranking' => [
                'desc(featured_home)',
                'desc(created_at)',
            ]
        ]
    ];

Then, I do \App\Job::setSettings(); on a command.

  1. It's creating two indexes: jobs_local and jobs_home. Shouldn't it be 'jobs_home_local`? When I upload to production it's going to be a conflict.
  2. It's setting up the attributes to index and custom ranking of jobs_local on the slave index (jobs_home). And the config for jobs_local is empty.

I am doing something wrong or is there a bug?

regards

Where's before indexing

I'm trying to index my dataset but i only want the data with the status of 1.
How would I achieve that because current efforts are not working.

$products = Product::where('status', 1)->reindex()->get();
        //$products->reindex();
        Product::setSettings();
        $count = count($products);
        return $count.' products sync\'d to Algolia';

"Call to undefined method Illuminate\Database\Query\Builder::reindex()"

Algolia Tags

Is there a way to add a tag to an Object when saving it to Algolia.

For examples I have users with a state relationship. I would like to save a tag depending on that relationship.

Then I can search by query and tag on the front end.

Thank You!

setSettings breaks when being called statically

I'm trying to reindex in the boot method of my model

public static $algoliaSettings = [
    'attributesForFaceting' => [
        // attribute list
    ]
];

protected static function boot()
{
    parent::boot();

    static::reindex();
}

However I get an 'array_keys() expects parameter 1 to be array' error on line 173 in AlgoliaEloquentTrait.php

Issue with Geolocation data (lat / lng) indexing

Geo-search overview expects geoloc array with lat and lng values.

How can I index in my database a geoloc array ? Should I store as string? Create a relational table called _geoloc? Use mySQL spatial point column?

[
{
objectID: "3797",
name: "John F Kennedy Intl",
city: "New York",
country: "United States",
iata_code: "JFK",
_geoloc: {
lat: 40.639751,
lng: -73.778925
},
links_count: 911
},
// […]
]

AutoIndex and AutoDelete will not work as documented

The documentation is incorrect in the usage of autoIndex and autoDelete.

Based on the code...

public function isAutoIndex(Model $model)
{
    return ($this->hasAlgoliaTrait($model) && (property_exists($model, 'autoIndex') == false || $model::$autoIndex === true));
}

public function isAutoDelete(Model $model)
{
    return ($this->hasAlgoliaTrait($model) && (property_exists($model, 'autoDelete') == false || $model::$autoDelete === true));
}

... you must declare these properties as either static...

public static $autoIndex = true;
public static $autoDelete = true;

... or change the way you reference them in the code. Additionally, the property_exists check will always fail as, if the property does exist on the model, property_exists will return true and you're checking against it being false.

public function isAutoIndex(Model $model)
{
    return ($this->hasAlgoliaTrait($model) && (property_exists($model, 'autoIndex') && $model->autoIndex === true));
}

public function isAutoDelete(Model $model)
{
    return ($this->hasAlgoliaTrait($model) && (property_exists($model, 'autoDelete') && $model->autoDelete === true));
}

Possible to target multiple indices with different attributes for each?

I see that it's possible to target multiple indices using public $indices and I also see that it's possible to specify which attributes are sent to an index using getAlgoliaRecord().

My question is, is it possible for a single Model to send different attributes to different indices?

_geoloc object can't be submitted via update method

When you attempt to update via the update() method, you can't send _geoloc. You can set it as an array, an object, whatever; it won't work. You get an error saying that _geoloc can't contain a string, and if you look at the body of the request in the logs, you can see it's sending _geoloc as blank.

Index prefixes

Does any besides me have a use case for dynamically setting prefixes on indexes? We run multiple sites out of one codebase with some key differences being decided by a site variable in the .env. With the index being set through a property I cannot use an expression (such as config('algolia.index-prefix')) to set it.

This could be accommodated with a fairly simple change to the code base. Simply changing the getFinalIndexName() method to the following (or similar):

public function getFinalIndexName(Model $model, $indexName)
{
    $index_prefix = method_exists($model, 'getPrefix') ? $model->getIndexPrefix().'_' : '';
    $env_suffix = property_exists($model, 'perEnvironment') && $model::$perEnvironment === true ? '_'.\App::environment() : '';

    return $index_prefix.$indexName.$env_suffix;
}

If the maintainers are interested in adding this I can submit a pull request.

Thanks!

AlgoliaEloquentTrait error in __callStatic method

I just figure out a minor issue in __callStatic method() method of "AlgoliaEloquentTrait".
I think the if condition at line 193 should be replaced by following because it prevents all Eloquent methods to be called:

if (method_exists($instance, $method)){
return call_user_func_array([$instance, $method], $parameters);
}else{
$method = str_replace("_","",$method);
return parent::__callStatic($method, $parameters);
}

$indices setting is being ignored.

So I had a "products" index and then I added a new model to my app called "services". Since the JS Helper won't allow me to query two indices at a time and I want to avoid the duplicated request, I decided to have "services" added to the "products" index as @pixelastic suggested.

I added the following to my Services model:

public $indices = [
    'products'
];

But the "products" model is not being updated after I do Services::reindex(). Any thoughts?

Legacy site with hard coded () in URLs

I'm working on a legacy site and it has has products with urls with bracket in:

https://kiltmakers.co.uk/products/scottish-gifts/pocket-watches-and-clocks/2-piece-thistle-gift-set-(pocket-watch-and-cufflinks)

Not ideal.

I'm using Laravel to upload the index to Algolia but its stripping out the brackets so the resultant url is:

https://kiltmakers.co.uk/products/scottish-gifts/Pocket%20Watches%20and%20Clocks/2-piece-thistle-gift-set-pocket-watch-and-cufflinks

Which gives a 404.

I've tried using url_encoding on the urls but that strips out all the dash - I just keep making things worse! Any suggestions for how I can get Laravel and Algolia to play nicely with the brackets?

Reindex Data with Relational Table

I have implemented Aloglia (laravel scout.) for my Movies table with actors as relational table and it works fine.

Problem:

When I update any movie its also updating algolia index (its good). But how can I update index if I made any change in relational table (for example update an actor of movie).

How to push a specific record manually with laravel scout.

Right now follwoing code is reindex all movies once i update any actor but its missing relational table actor althogh I have toSearchableArray in Movies model

Actor Controller Update Method

public function update(Actor $actor,Request $request){
	$actor->fill($request->all())->save();
	Movie::reindex();
}

In my Movie model


    public function toSearchableArray(){
		$extra_data = [];
		$extra_data['actors'] = array_map(function ($data) {
		     return [
                            'name' => $data['name'],
                             'age' =>$data['age']
                      ];
		}, $this->actors->toArray());
		
	        return array_merge($this->toArray(), $extra_data);
	}

and if I run
php artisan scout:import "App\Movie"
everything work properly ...

Hosts unreachable:Resolving timed out after 2000 milliseconds

i'm running algolia with laravel 5.1 using this package,but i got the erros when i try to index some data or setup a search.

2015-11-08_17-36-32

already went throught this issue,but i could not solved my problem

running laravel 5.1 with homestead Laravel Homestead version 2.1.6, tried ls /etc/ssl/certs | grep -i comodo

Comodo_AAA_Services_root.pem
COMODO_Certification_Authority.pem
COMODO_ECC_Certification_Authority.pem
Comodo_Secure_Services_root.pem
Comodo_Trusted_Services_root.pem

a guy from china,any case that the internet was block by the Great Wall? because when i use my VPN connect to the internet. it works fine....

i push it to production,still got the errors. any ideas

Index subset & add to index

Hey.

Is it possible to add to the indexed subset of data?

Eg. I would like to add $user->name to my subset of data as user_name, this is to prevent having to load the entire user model on every single search which shows this data.

Let's say my model contains these attributes:
[
'id' => int,
'name' => str,
'email' => str
]

I don't want the email to be searchable, therefore I'll set the data to return a subset, in this case it's just the name.

now we have:
[
'id' => int,
'name' => str
]

Lastly, I would like to add a single relationship attribute to this data and end up with:
[
'id' => int,
'name' => str,
'emergency_contact' => $this->contact->name
]

Finally, index this data, possible?

Snake Case Question

There are some variables in this project that uses snake_case instead of camelCase. Is this intentional or just for this project? In the Laravel world camelCase is preferred.

autoIndex and autoDelete do not works on Eloquent builders

Hello,

When I trigger updates and deletes from the Eloquent builder, the Algolia indexes are not touched :
This doesn't work

Ad::where('id', $adId)->update($attributes);

This does work

Ad::find($adId)->update($attributes);

I have the same problem with the delete() method.

What am I missing here and why is it working only with Models : this forces me to do two requests find() + update() rather than only one update().

Trying to get property of a non object

Trying to get property of a non object @foreach($items as $item) $items->image

Search controller

<?php

class SearchController extends \BaseController {

    /**
     * Display a listing of the resource.
     * GET /search
     *
     * @return Response
     */
    public function index()
    {
        $query = Input::get('q');

        if(!$query)
        {
            App::abort(404);
        }

        if($query[0] == '#')
        {
            $hash = substr($query, 1);
            $hashTag = Hashtag::where('hashtag', $hash)->first();
            if ($hashTag)
                return Redirect::to(URL::route('brand-item', ['brandname' => $hashTag->item->brand->name, 'item' => $hashTag->item->name]));
        }

        $items = Item::search($query);

        return View::make('search.index')->with('items', $items);
    }
}

Indexing through relationships

I have a post, and this post must have one category. The category is defined via an Eloquent relationship, so the only thing about the category on the Post model is the id. However, I want to be able to make the post searchable by category. How would I do this, even though I cannot add the category's name as an indexing parameter as it isn't actually on the Post model?

Cannot add object when Model ID is binary

The ID of my table is a binary UUID. The Algolia traits throws a 400 exception when saving a model instance and I see that it calls an API entry with a bad path:
AlgoliaException in Client.php line 562:
400 in Client.php line 562
at Client->doRequest(object(ClientContext), 'PUT', 'LTNCXQAANN.algolia.net', '/1/indexes/blbm_me/%11%E5%C1%1A%E9%3B%84%E0%84X%00%11%223DU' ...

Note that setting the $autoIndex = false and using the pushToIndex() method is working well to save the model.

I think that the problem is coming from the EloquentSubscriber.php file, function saved():
$index->addObject($this->modelHelper->getAlgoliaRecord($model), $this->modelHelper->getKey($model));
It uses the getKey() function which returns the raw binary ID and may be it should use the getObjectId() function as I set the $objectIdKey variable in the model to the name of the computed field containing the "stringified" version of the ID.

.

Namespace Changes

What about renaming the namespace to AlgoliaSearch\Laravel instead of Algolia\AlgoliasearchLaravel? Then it will be more inline with the API PHP package for Algolia.

Models using the Algolia trait appear broken

If you apply an Algolia trait to a model and attempt to then call the static find() method on the model, you will receive an error.

BadMethodCallException in Builder.php line 1992: Call to undefined method Illuminate\Database\Query\Builder::_find()

It can be traced to the following method in the AlgoliaEloquentTrait trait:

public static function __callStatic($method, $parameters)
{
    $instance = new static();

    $method = '_'.$method;

    if (method_exists($instance, $method));

    return call_user_func_array([$instance, $method], $parameters);

    return parent::__callStatic($method, $parameters);
}

This code will always attempt to call the method even if it might not exist due to the broken if statement. Looks like it might have been a merge issue but even the pre-merge code would have broken due to the else scenario still attempting to call the underscore overload method.

Setting distinct for an index by default using $algoliaSettings

Greetings,

I have a model set up to automatically sync to Algolia and for this index I would like to have the field called category to be distinct by default for all queries. In my Eloquent model, part of my $algoliaSettings look like this:

public $algoliaSettings = [
    'attributeForDistinct' => 'category'
];

When I call Model::setSettings() and then take a look at the index display settings in the web app, I see this:

screen shot 2016-03-16 at 9 43 32 am

The distinct true/false option is not set. I have looked through the documentation here and on Algolia and cannot find anything that will allow me to programmatically set distinct to true for all queries. Does this feature exist? And do you know of any way I can mark distinct as true without logging in and manually setting it each time I need to update the index settings?

Thanks for the help!

Indexing many records with relationships

Hi !

I'm trying to index many rows of my database (about 20000) in Algolia, so i tried 2 solutions :
• Class:reindex() make 4 or 5 SQL queries for every rows so it takes a very long time to fetch all datas.
• Object->pushToIndex() after i fetch datas from database but it seems to take a long time to send data to Algolia server.

Is there a solution for my case ?

Hosts unreachable

I've done a fresh install of Homestead, VirtualBox, freshly downloaded the Vagrant box and am using the latest version algoliasearch-laravel however for some reason I'm getting this error:

AlgoliaException in Client.php line 748:
Hosts unreachable: Could not resolve host: WWPOIMBJ3Z
.algolia.net,Could not resolve host: WWPOIMBJ3Z
-3.algolianet.com,Could not resolve host: WWPOIMBJ3Z
-1.algolianet.com,Could not resolve host: WWPOIMBJ3Z
-2.algolianet.com

We've been using Algolia for 6 months and this is the first time I've had this issue and I'm stumped as to how to resolve it?

Reindexing wipes out other settings

When running reindex(), it overwrites the settings which is not being specified in the class $algoliaSettings variable. I believe we should preserve other settings if they exist in Algolia and are not specified on $algoliaSettings.

The area to fix should be in $modelHelper->getIndicesTmp(), when we initiating the tmp index, we should clone the original index's setting over.

Algolia Exception: No content in PUT request

Hi, I'm having trouble getting Algolia to index my model. After following the instructions to set it up (require it in with composer, add class to providers array, publish vendor and update config API keys, and adding trait to model class) I am getting the following error when making a POST request on a form submission:

AlgoliaException in Client.php line 910:
No content in PUT request
in Client.php line 910
at Client->doRequest(object(ClientContext), 'PUT', 'K0QKLYIYQ7.algolia.net', '/1/indexes/activities/4', array(), array('category_id' => '1', 'activityTitleNor' => 'Dette er an test', 'activityDescriptionNor' => 'Test ', 'price' => '200', 'supplier_id' => '1', 'safetyNor' => 'Supersafe', 'updated_at' => '2016-05-21 01:53:46', 'created_at' => '2016-05-21 01:53:46', 'id' => '4', 'objectID' => '4'), '2', '30') in Client.php line 738

Now after looking around for two days on google trying to locate any information about this issue I've failed to resolve it on my own, this leads me to believe that it's either A) so obvious to experienced developers that no one thought to put the information anywhere or B) a new issue.

I'm running laravel 5.2 on Homestead.

Invalid argument supplied for foreach()

Hello,
I got this error "Invalid argument supplied for foreach()" when I am trying to foreach results
this is a code

$results = Cartalyst\Sentinel\Users\EloquentUser::search('arina');
if (is_array($results)) {
    foreach ($results as $result) {
        foreach ($result as $a) {
            $name = $a['full_name'];
        }
    }
} 

Insert all data at once

Can anyone please tell me how can i insert all table rows at once like in "algolia-php" library $algolia->saveObject($rows);

Update relationships

Hello.

How I update relationship data once that relationship has been updated?

Eg. I have a car with a passenger relationship. I load the passenger into Algolia along with the car, but whenever the passenger is updated, nothing happens to the Car index where the passenger is also loaded.

It cannot be correct that I have to reindex everything every time.

PSR-2, PHP-FIG and Contribution Guidelines

What about adding PSR-2 styled syntax and follow naming conventions specified in PHP-FIG? Below is an example file of contributing guidelines (CONTRIBUTING.md).


CONTRIBUTING

Contributions are welcome, and are accepted via pull requests. Please review these guidelines before submitting any pull requests.

Guidelines

  • Please follow the PSR-2 Coding Standard and PHP-FIG Naming Conventions.
  • Ensure that the current tests pass, and if you've added something new, add the tests where relevant.
  • Remember that we follow SemVer. If you are changing the behaviour, or the public api, you may need to update the docs.
  • Send a coherent commit history, making sure each individual commit in your pull request is meaningful. If you had to make multiple intermediate commits while developing, please squash them before submitting.
  • You may also need to rebase to avoid merge conflicts.

Running Tests

You will need an install of Composer before continuing.

First, install the dependencies:

$ composer install

Then run phpunit:

$ vendor/bin/phpunit

If the test suite passes on your local machine you should be good to go.

When you make a pull request, the tests will automatically be run again by Travis CI on multiple php versions and hhvm.


What do you think? Something you guys would consider adding?

algoliaSettings

Where can I find a full list of settings I can apply to indexes?
Im currently looking for Query words interpretation setting.

$algoliaSettings['attributesForFaceting'] setting is being ignored.

Hi there,

Each time I run Product::reindex(); the attributesForFaceting setting gets cleared on my dashboard and I must login and update it manually. Am I doing it wrong?

class Product extends \ResourceModel {
    use AlgoliaEloquentTrait;
    public static $perEnvironment = true;
    public static $autoIndex = true;
    public $algoliaSettings = [
        'attributesForFaceting' => [ 'category_id', 'vendor_id', 'unit_price', 'brand' ],
    ];
}

Thanks in advance!

Relationshipped data is not stored when in pivot table.

Hello,

I've a problem with Algolia Search Client using Laravel 5.1 and SQLite (development environment).

I've enabled auto-indexing, however the relationship data is not saved when creating a new record.

This is roughly the codes in my model:

public $indices;
public static $autoIndex = true;
public static $autoDelete = true;

public function __construct($attributes = [])
{
    parent::__construct($attributes);
    $this->indices = [config('algolia.connections.' . config('algolia.default') . '.indice_name')];
}

public function getAlgoliaRecord()
{
    /**
     * Load the user relation so that it's available
     *  in the laravel toArray method
     */
    $this->user;
    $this->tags;

    // When we set this method, $algoliaSettings is ignored, so we've to strip the function this:
    $allowed = $this->algoliaSettings['searchableAttributes'];
    $elements = array_intersect_key($this->toArray(), array_flip($allowed));

    return array_merge($elements, [
        'img_src' => config('whatthetag.s3_storage_cdn_domain') . config('whatthetag.uploads_folder') . '/' . $this->image,
        'thumb_src' => Croppa::url('/'. config('whatthetag.uploads_folder') .'/'.$this->image, 400, 300),
        'url' => config('app.url') . '/photo/detail/' . $this->slug,
        'user_name' => $this->user->name,
        'tags' => array_map(function ($data) {
            return [
                'title' => $data['title'],
                'slug'  => $data['slug'],
            ];
        }, $this->tags->toArray())
    ]);
}


public $algoliaSettings = [
    'attributesToHighlight' => [
        'title',
        'user_name',
        'tags',
    ],
    'searchableAttributes' => [
        'id',
        'title',
        'url',
        'img_src',
        'thumb_src',
        'user_name',
        'tags',
    ],
    'customRanking' => [
        'desc(popularity)',
        //'desc(id)',
    ],
];


public function tags()
{
    return $this->belongsToMany('App\Tag', 'photo_tag')
        ->withTimestamps();
}

public function user()
{
    return $this->belongsTo('App\User', 'user_id');
}

And this is roughy the photo creation code:

$photo            = new Photo;
$photo->user_id    = Auth::id();
$photo->title    = $request->get('title');
$photo->image    = $upload['filename'];
$photo->save();
$photo->tags()->attach($tagIds);

As you can see, the user_name string and the tags array comes from a string.

The user_name field is added when creating a new row, however the tags array is just blank (tags: [] in algolia panel when I look for it)

However, when I do Model::reindex() I can see the tags just fine.

I'm guessing it's because after the row is created the pivot table relation is not created yet.

How can I fix this ? This is becoming quite annoying and I don't want to manually run Model::reindex() or $photo->touch() for such a simple task.

Thanks in advance,

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.