Utilisation des ActiveRecord

Pour des informations générales sur l'utilisation d'ActiveRecord avec yii, référez-vous à cette section du guide.

Afin de dĂ©finir une classe ActiveRecord elasticsearch, votre classe doit Ă©tendre yii\elasticsearch\ActiveRecord et implĂ©menter au moins la mĂ©thode attributes() pour dĂ©finir les attributes de votre enregistrement. La gestion des clefs primaires est diffĂ©rente dans elasticsearch, Ă©tant donnĂ© que la clef primaire (le champ _id dans elasticsearch) ne fait pas partie des attributs par dĂ©faut. Il est cependant possible de dĂ©finir un mapping de path pour que le champ _id fasse partie des attributs. RĂ©fĂ©rez-vous Ă  la documentation elasticsearch pour voir comment le dĂ©finir. Le champ _id d'un document/enregistrement peut ĂȘtre accĂ©dĂ© en utilisant getPrimaryKey() et setPrimaryKey(). Lorsque le mapping de path est dĂ©fini, le nom de l'attribut peut ĂȘtre dĂ©fini en utilisant la mĂ©thode primaryKey().

Voici un modÚle d'exemple nommé Customer:

class Customer extends \yii\elasticsearch\ActiveRecord
{
    /**
     * @return array the list of attributes for this record
     */
    public function attributes()
    {
        // le mapping de '_id' est configuré pour le champ 'id'
        return ['id', 'name', 'address', 'registration_date'];
    }

    /**
     * @return ActiveQuery defines a relation to the Order record (can be in other database, e.g. redis or sql)
     */
    public function getOrders()
    {
        return $this->hasMany(Order::className(), ['customer_id' => 'id'])->orderBy('id');
    }

    /**
     * Defines a scope that modifies the `$query` to return only active(status = 1) customers
     */
    public static function active($query)
    {
        $query->andWhere(['status' => 1]);
    }
}

Vous pouvez surcharger index() et type() pour définir l'index et type que cet enregistrement représente.

L'utilisation des ActiveRecord elasticsearch est trĂšs similaire Ă  celle d'ActiveRecord pour les bases de donnĂ©es, et qui est dĂ©crite dans le guide. Elle supporte la mĂȘme interface et les mĂȘmes fonctionnalitĂ©s, exceptions faite des limitations et additions suivantes (!) :

  • Etant donnĂ© que elasticsearch ne supporte pas SQL, l'API de requĂȘtes ne supporte pas join(), groupBy(), having() and union(). Les tris, limites, dĂ©callages et conditions sont tous supportĂ©s.
  • from() ne sĂ©lectionne pas les tables, mais les index et type sur lesquels la requĂȘte sera exĂ©cutĂ©e.
  • select() a Ă©tĂ© remplacĂ©e par fields() qui fait globalement la mĂȘme chose, le terme fields Ă©tant plus orientĂ© vers la terminologie elasticsearch. Cette mĂ©thode dĂ©finit les champs Ă  rĂ©cupĂ©rer dans le document.
  • Les relations yii\elasticsearch\ActiveQuery::via() ne peuvent ĂȘtre dĂ©finies via une table Ă©tant donnĂ© qu'il n'y a pas de tables dans elasticsearch. Vous pouvez uniquement dĂ©finir des relations avec les autres enregistrements.
  • Etant donnĂ© qu'elasticsearch n'est pas uniquement fait pour le stockage des donnĂ©es, mais Ă©galement pour les rechercher, le support de la recherche a Ă©tĂ© implĂ©mentĂ©. Les mĂ©thodes query(), filter() et yii\elasticsearch\ActiveQuery::addFacet() permettent de dĂ©finir une requĂȘte elasticsearch. Regardez l'exemple suivant pour comprendre leur fonctionnement et voir l'utilisation des Query DSL pour composer les parties query et filter.
  • Il est aussi possible de dĂ©finir des relations entre des ActiveRecord elasticsearch et des ActiveRecord normaux, et vice versa.

NOTE: elasticsearch limite le nombre d'enregistrements retournĂ©s par n'importe quelle requĂȘte Ă  10 enregistrements par dĂ©faut. Si vous vous attendez Ă  obtenir plus de rĂ©sultats, vous devez explicitement dĂ©finir leur nombre dans la requĂȘte et Ă©galement dans la dĂ©finition de la relation. Ceci est Ă©galement important pour les relations qui utilisent via(), Ă©tant donnĂ© que si les enregistrements "via" sont limitĂ©s Ă  10, les enregistrements liĂ©s ne pourront Ă©galement pas dĂ©passer la limite de 10.

Exemple d'utilisation :

$customer = new Customer();
$customer->primaryKey = 1; // ici, équivalent à $customer->id = 1;
$customer->attributes = ['name' => 'test'];
$customer->save();

$customer = Customer::get(1); // récupÚre un document par pk
$customers = Customer::mget([1,2,3]); // récupÚre plusieurs documents par pk
$customer = Customer::find()->where(['name' => 'test'])->one(); // rĂ©cupĂšre par requĂȘte, vous devez configurer le mapping de ce champ afin que la recherche fonctionne correctement
$customers = Customer::find()->active()->all(); // rĂ©cupĂšre l'ensemble des documents en utilisant une requĂȘte (et le scope `active`)

// http://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-match-query.html
$result = Article::find()->query(["match" => ["title" => "yii"]])->all(); // articles dont le titre contient "yii"

// http://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-flt-query.html
$query = Article::find()->query([
    "fuzzy_like_this" => [
        "fields" => ["title", "description"],
        "like_text" => "Cette requĂȘte retournera les articles similaires Ă  ce texte :-)",
        "max_query_terms" => 12
    ]
]);

$query->all(); // retourne l'ensemble des documents
// vous pouvez ajouter des facets Ă  votre recherche :
$query->addStatisticalFacet('click_stats', ['field' => 'visit_count']);
$query->search(); // retourne l'ensemble des documents + des statistiques Ă  propos du champ visit_count (minimum, maximum, somme, ..)

Et beaucoup plus. "Ce que vous pouvez bĂątir est infini"?