Fermer

décembre 18, 2023

Optimizely Commerce personnalisation de l’index Elasticsearch V7

Optimizely Commerce personnalisation de l’index Elasticsearch V7


Le commerce configuré de manière optimisée introduit Elasticsearch v7 pour une meilleure expérience de recherche. Dans le paysage dynamique du monde du commerce, il est toujours possible d’étendre la personnalisation du code. De plus, Optimizely fournit des étapes explicites pour personnaliser les index Elasticsearch v7.

L’utilisation d’Elasticsearch v7 présente de nombreux avantages. certains sont

  • Performance améliorée
  • Améliorations de la sécurité
  • SQL d’ElasticSearch
  • Prise en charge de GeoJSON
  • Convivialité et fonctionnalités conviviales pour les développeurs

Dans cet article, nous verrons étape par étape comment nous ajouterons la colonne personnalisée dans l’index Elasticsearch v7.

Définition d’Elasticsearch v7 comme fournisseur par défaut depuis l’administrateur

La toute première étape consiste à définir un fournisseur par défaut dans l’administrateur. Vous trouverez ci-dessous les étapes pour définir le fournisseur par défaut :

  1. Connectez-vous à l’administrateur
  2. Accédez aux paramètres
  3. Recherchez « Nom du fournisseur de recherche »
  4. Définissez Elasticsearch v7 dans « Nom du fournisseur de recherche » et « Nom de l’indexeur de recherche » (voir capture d’écran)
  5. Cliquez sur Enregistrer.

Création d’un champ personnalisé

Une fois que la section d’administration a défini le fournisseur par défaut, le site pointera vers Elasticsearch v7 et effectuera des recherches sur les index nouvellement créés par Elasticsearch v7.

Si nous souhaitons ajouter un nouveau champ personnalisé à ces index, Optimizely fournit des pipelines pour ajouter le nouveau champ personnalisé.

Ajoutez une classe dans la solution pour étendre la classe ElasticsearchProduct et créer un nouveau champ

Dans cette classe, nous avons créé une propriété nommée StockedInWharehouses qui est le type de liste de chaînes.

namespace Extensions.Search.ElasticsearchV7.DocumentTypes.Product
{
 using Insite.Search.ElasticsearchV7.DocumentTypes.Product;
 using Nest7;

 [ElasticsearchType(RelationName = "product")]
 public class ElasticsearchProductCustom : ElasticsearchProduct
 {
     public ElasticsearchProductCustom(ElasticsearchProduct source)
         : base(source) // This constructor copies all base code properties.
     {
     }

     [Keyword(Index = true, Name = "stockedInWarehouses")]
     public List<string> StockedInWarehouses { get; set; }
 }
}

Remplacer le pipeline pour insérer des données dans une propriété personnalisée

Pour ajouter les données dans une propriété personnalisée, utilisez une extension de classe PrepareToRetrieveIndexableProducts. Ici, prenez soin de récupérer les données dans du code personnalisé, c’est-à-dire, écrivez une requête LINQ pour récupérer les données. Les meilleures performances sont obtenues en retournant Dictonary like.ToDictionary(record => record.ProductId). Voici un exemple d’extrait de code

namespace Extensions.Search.ElasticsearchV7.DocumentTypes.Product.Index.Pipelines.Pipes.PrepareToRetrieveIndexableProducts
{
 using Insite.Core.Interfaces.Data;
 using Insite.Core.Plugins.Pipelines;
 using Insite.Data.Entities;
 using Insite.Search.ElasticsearchV7.DocumentTypes.Product.Index.Pipelines.Parameters;
 using Insite.Search.ElasticsearchV7.DocumentTypes.Product.Index.Pipelines.Results;
 using System.Linq;

 public sealed class PrepareToRetrieveIndexableProducts : IPipe<PrepareToRetrieveIndexableProductsParameter, PrepareToRetrieveIndexableProductsResult>
 {
     public int Order => 0; // This pipeline has no base code so Order can be anything.

     public PrepareToRetrieveIndexableProductsResult Execute(IUnitOfWork unitOfWork, PrepareToRetrieveIndexableProductsParameter parameter, PrepareToRetrieveIndexableProductsResult result)
     {
         result.RetrieveIndexableProductsPreparation = unitOfWork.GetRepository<ProductWarehouse>().GetTableAsNoTracking()
               .Join(unitOfWork.GetRepository<Product>().GetTableAsNoTracking(), x => x.ProductId, y => y.Id, (x, y) => new { prodWarehouse = x })
               .Join(unitOfWork.GetRepository<Warehouse>().GetTableAsNoTracking(), x => x.prodWarehouse.WarehouseId, y => y.Id, (x, y) => new { Name = y.Name, productId = x.prodWarehouse.ProductId })
               .GroupBy(z => z.productId).ToList()
               .Select(p => new {
                   productId = p.Key.ToString(),
                   warehouses = string.Join(",", p.Select(i => i.Name))
               })
               .ToDictionary(z => z.productId, x => x.warehouses);

         return result;
     }
 }
}

Attribuer des données à une propriété personnalisée dans Elasticsearch7

Après avoir récupéré les données dans la propriété de résultat « RetrieveIndexableProductsPreparation », définissez les données dans une propriété personnalisée pour les produits indexables. Pour réaliser cette caisse, créez une classe « ExtendElasticsearchProduct » et étendez-la avec IPipe

Ici, dans la méthode d’exécution, le paramètre contient la propriété RetrieveIndexableProductsPreparation et celle-ci contient nos données. Récupérez ces données à l’aide de la méthode TryGetValue.

Évitez d’avoir la logique pour récupérer les données renvoyées dans la classe d’extension CreateElasticsearchProductResult. L’écriture de la logique de récupération de données dans cette classe aura un impact sur les performances de création des index de produits.

Vous trouverez ici un extrait de code illustratif :

namespace Extensions.Search.ElasticsearchV7.DocumentTypes.Product.Index.Pipelines.Pipes.CreateElasticsearchProduct
{
 using System;
 using System.Collections.Generic;
 using Insite.Core.Interfaces.Data;
 using Insite.Core.Plugins.Pipelines;
 using Insite.Search.ElasticsearchV7.DocumentTypes.Product.Index.Pipelines.Parameters;
 using Insite.Search.ElasticsearchV7.DocumentTypes.Product.Index.Pipelines.Results;

 public sealed class ExtendElasticsearchProduct : IPipe<CreateElasticsearchProductParameter, CreateElasticsearchProductResult>
 {
     public int Order => 150;

     public CreateElasticsearchProductResult Execute(IUnitOfWork unitOfWork, CreateElasticsearchProductParameter parameter, CreateElasticsearchProductResult result)
     {
         var elasticsearchProductCustom = new ElasticsearchProductCustom(result.ElasticsearchProduct);

         if (((Dictionary<Guid, int>)parameter.RetrieveIndexableProductsPreparation).TryGetValue(elasticsearchProductCustom.ProductId.ToString(), out var stockedInWarehouses))
         {
            elasticsearchProductCustom.StockedInWarehouses = ExtractList(stockedInWarehouses);
         }

         result.ElasticsearchProduct = elasticsearchProductCustom;

         return result;
     }

     private static List<string> ExtractList(string content)
     {
       if (string.IsNullOrWhiteSpace(content))
         return new List<string>();
       return content
        .Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
        .ToList();
     }
 }
}

Après avoir reconstruit l’index de produits complet, il affiche la colonne « StockedInWarehouses » nouvellement créée dans les index de produits. La capture d’écran ci-dessous montrant l’index avec la valeur

Requête de terme pour filtrer StockedInWarehouses

Vous pouvez désormais facilement utiliser le champ StockedInWarehouses dans une requête de terme pour filtrer les résultats de recherche.

var currentWarehouseId = SiteContext.Current.PickUpWarehouseDto == null
   ? SiteContext.Current.WarehouseDto.Name
   : SiteContext.Current.PickUpWarehouseDto.Name;  
 
result.StockedItemsOnlyQuery = result
      .SearchQueryBuilder
      .MakeTermQuery("stockedInWarehouses.keyword", currentWarehouseId);

Lien de référence : https://docs.developers.optimizely.com/configured-commerce/docs/customize-the-search-rebuild-process






Source link

décembre 18, 2023