сопоставление объектов для [fieldName] попыталось проанализировать поле [null] как объект, но обнаружило конкретное значение (ElasticSearch 7, NEST 7) - PullRequest
0 голосов
/ 27 мая 2020

Я использую ElarsticSearch 7.7 и NEST 7.7 и пытаюсь использовать массовую загрузку Elasti c Search 7. У меня есть основная модель и одна вложенная модель. Когда я загружаю список продуктов, я получаю сообщение об ошибке ниже.

# Invalid Bulk items:
  operation[0]: update returned 400 _index: jm-dev-products _type: _doc _id: 0 _version: 0 error: Type: mapper_parsing_exception Reason: "object mapping for [associatedProducts.categoryIds] tried to parse field [null] as object, but found a concrete value"
  operation[1]: update returned 400 _index: jm-dev-products _type: _doc _id: 0 _version: 0 error: Type: mapper_parsing_exception Reason: "object mapping for [availableStores] tried to parse field [null] as object, but found a concrete value"
  operation[2]: update returned 400 _index: jm-dev-products _type: _doc _id: 0 _version: 0 error: Type: mapper_parsing_exception Reason: "object mapping for [availableStores] tried to parse field [null] as object, but found a concrete value"

Я упомянул Список также как [Вложенный]. Но я видел сообщение, в котором говорится, что этот список также упоминается как [Число].

Я доказываю большую часть своего кода, потому что его может использовать любой.

Это родительская модель, и она имеет AssociatedProducts как вложенные.

 [ElasticsearchType(RelationName = "searchproduct")]
    public class ElasticIndexGroupProduct
    {
        [Number(DocValues = false, IgnoreMalformed = true, Coerce = true)]
        public int Id { get; set; }

        [Date]
        public DateTime IndexDate { get; set; }

        [Number(DocValues = false, IgnoreMalformed = true, Coerce = true)]
        public int ProductId { get; set; } 

        [Text]
        public string PartNumber { get; set; }

        [Text]
        public string Name { get; set; }

        [Text]
        public string MetaKeywords { get; set; }

        [Text]
        public string MetaDescription { get; set; }

        [Text]
        public string MetaTitle { get; set; }

        [Boolean(NullValue = false, Store = true)]
        public bool LimitedToStores { get; set; }

        [Number(DocValues = false, IgnoreMalformed = true, Coerce = true)]
        public List<int> AvailableStores { get; set; }

        [Text]
        public string ShortDescription { get; set; }

        [Text]
        public string FullDescription { get; set; }

        [Text]
        public string SeName { get; set; }

        [Nested]
        [PropertyName("associatedProducts")]
        public IList<ElasticIndexAssociatedProduct> AssociatedProducts { get; set; }

        [Number(DocValues = false, IgnoreMalformed = true, Coerce = true)]
        public List<int> AssociatedProductIds { get; set; }

        [Boolean(NullValue = false, Store = true)]
        public bool StockAvailability { get; set; }

        [Number(DocValues = false, IgnoreMalformed = true, Coerce = true)]
        public int DeliveryDateId { get; set; }

        [Text]
        public string DeliveryDateName { get; set; }

        [Text]
        public string CategoryName { get; set; }

        [Number(DocValues = false, IgnoreMalformed = true, Coerce = true)]
        public int CategoryId { get; set; }

        [Number(DocValues = false, IgnoreMalformed = true, Coerce = true)]
        public List<int> CategoryIdsLimitToStore { get; set; }

        [Text]
        public string CategoryParentNamesStr { get; set; }

        [Number(DocValues = false, IgnoreMalformed = true, Coerce = true)]
        public List<int> CategoryIds { get; set; }

        [Text]
        public string CategoryIdsStr { get; set; }

        [Boolean(NullValue = false, Store = true)]
        public bool IsPublishedCategory { get; set; }

        [Text]
        public string ManufacturerNumber { get; set; }

        [Text]
        public string ManufacturerName { get; set; }

        [Number(DocValues = false, IgnoreMalformed = true, Coerce = true)]
        public int ManufacturerId { get; set; }

        [Boolean(NullValue = false, Store = true)]
        public bool ManufacturerLimitToStore { get; set; }

        [Boolean(NullValue = false, Store = true)]
        public bool IsPublishedManufacturer { get; set; }

        [Number(DocValues = false, IgnoreMalformed = true, Coerce = true)]
        public decimal Price { get; set; }

        [Text]
        public string VendorName { get; set; }

        [Text]
        public string VendorSeName { get; set; }

        [Text]
        public string ProductPictureUrl { get; set; }

        [Boolean(NullValue = false, Store = true)]
        public bool HasImage { get; set; }
    }

это вложенная модель

[ElasticsearchType]
    public class ElasticIndexAssociatedProduct
    {

        [Number(DocValues = false, IgnoreMalformed = true, Coerce = true)]
        public int ProductId { get; set; }

        [Text]
        public string PartNumber { get; set; }

        [Text]
        public string Name { get; set; }

        [Text]
        public string MetaKeywords { get; set; }

        [Text]
        public string MetaDescription { get; set; }

        [Text]
        public string MetaTitle { get; set; }

        [Boolean(NullValue = false, Store = true)]
        public bool LimitedToStores { get; set; }

        [Number(DocValues = false, IgnoreMalformed = true, Coerce = true)]
        public List<int> AvailableStores { get; set; }

        [Text]
        public string ShortDescription { get; set; }

        [Text]
        public string FullDescription { get; set; }

        [Text]
        public string SeName { get; set; }

        [Boolean(NullValue = false, Store = true)]
        public bool StockAvailability { get; set; }

        [Number(DocValues = false, IgnoreMalformed = true, Coerce = true)]
        public int DeliveryDateId { get; set; }

        [Text]
        public string DeliveryDateName { get; set; }

        [Text]
        public string CategoryName { get; set; }

        [Number(DocValues = false, IgnoreMalformed = true, Coerce = true)]
        public int CategoryId { get; set; }

        [Number(DocValues = false, IgnoreMalformed = true, Coerce = true)]
        public List<int> CategoryIdsLimitToStore { get; set; }

        [Text]
        public string CategoryParentNamesStr { get; set; }

        [Number(DocValues = false, IgnoreMalformed = true, Coerce = true)]
        public List<int> CategoryIds { get; set; }

        [Text]
        public string CategoryIdsStr { get; set; }

        [Boolean(NullValue = false, Store = true)]
        public bool IsPublishedCategory { get; set; }

        [Text]
        public string ManufacturerNumber { get; set; }

        [Text]
        public string ManufacturerName { get; set; }

        [Number(DocValues = false, IgnoreMalformed = true, Coerce = true)]
        public int ManufacturerId { get; set; }

        [Boolean(NullValue = false, Store = true)]
        public bool ManufacturerLimitToStore { get; set; }

        [Boolean(NullValue = false, Store = true)]
        public bool IsPublishedManufacturer { get; set; }

        [Number(DocValues = false, IgnoreMalformed = true, Coerce = true)]
        public decimal Price { get; set; }

        [Text]
        public string VendorName { get; set; }

        [Text]
        public string VendorSeName { get; set; }

        [Text]
        public string ProductPictureUrl { get; set; }

        [Boolean(NullValue = false, Store = true)]
        public bool HasImage { get; set; }

        [Text]
        public string Specification { get;  set; }
    }

Это методы привязки данных

public static class IndexProductMappingExtension
    {
        public static async Task<ElasticIndexGroupProduct> ToIndexModel(this ElasticIndexGroupProductEntity model, JM_Core_ObjectContext jmContext, IDataProvider dataProvider, string imageUrlPrefix)
        {
            if (model == null)
                return null;

            var entity = new ElasticIndexGroupProduct();
            entity.IndexDate = model.IndexDate;
            entity.ProductId = model.ProductId;
            entity.PartNumber = model.PartNumber;
            entity.Name = model.Name;
            entity.MetaKeywords = model.MetaKeywords ?? string.Empty;
            entity.MetaDescription = model.MetaDescription ?? string.Empty;
            entity.MetaTitle = model.MetaTitle ?? string.Empty;
            entity.LimitedToStores = model.LimitedToStores;
            entity.AvailableStores = !string.IsNullOrEmpty(model.AvailableStores) ? model.AvailableStores.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(i => Convert.ToInt32(i)).ToList() :null;
            entity.ShortDescription = model.ShortDescription ?? string.Empty;
            entity.FullDescription = model.FullDescription ?? string.Empty;
            entity.SeName = model.SeName ?? string.Empty;
            entity.StockAvailability = model.StockAvailability;
            entity.DeliveryDateId = model.DeliveryDateId;
            entity.DeliveryDateName = model.DeliveryDateName ?? string.Empty;
            entity.CategoryName = model.CategoryName ?? string.Empty;
            entity.CategoryId = model.CategoryId;
            entity.CategoryIdsLimitToStore = !string.IsNullOrEmpty(model.CategoryIdsLimitToStore) ? model.CategoryIdsLimitToStore.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(i => Convert.ToInt32(i)).ToList() : null;
            entity.CategoryParentNamesStr = model.CategoryParentNamesStr ?? string.Empty;
            entity.CategoryIds =!string.IsNullOrEmpty(model.CategoryIdsStr) ? model.CategoryIdsStr.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(i => Convert.ToInt32(i)).ToList() : null;
            entity.CategoryIdsStr = model.CategoryIdsStr ?? string.Empty;
            entity.IsPublishedCategory = model.IsPublishedCategory;
            entity.ManufacturerNumber = model.ManufacturerNumber ?? string.Empty;
            entity.ManufacturerName = model.ManufacturerName ?? string.Empty;
            entity.ManufacturerId = model.ManufacturerId;
            entity.ManufacturerLimitToStore = model.ManufacturerLimitToStore;
            entity.IsPublishedManufacturer = model.IsPublishedManufacturer;
            entity.Price = model.Price;
            entity.VendorName = model.VendorName ?? string.Empty;
            entity.VendorSeName = model.VendorSeName ?? string.Empty;
            entity.ProductPictureUrl = model.HasImage ? (imageUrlPrefix + model.ProductPictureUrl) : string.Empty;
            entity.HasImage = model.HasImage;

            if (!string.IsNullOrEmpty(model.AssociatedProducts))
            {
                entity.AssociatedProductIds = model.AssociatedProducts.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(i => Convert.ToInt32(i)).ToList();
                entity.AssociatedProducts = await GetAssociatedProducts(entity.AssociatedProductIds, jmContext, dataProvider, imageUrlPrefix);
            }
            return entity;
        }

        private static async Task<IList<ElasticIndexAssociatedProduct>> GetAssociatedProducts(List<int> associatedProductIds, JM_Core_ObjectContext jmContext, IDataProvider dataProvider, string imageUrlPrefix)
        {
            var pProductIds = dataProvider.GetStringParameter("ProductIds", string.Join(",", associatedProductIds));
            var associatedToIndex = await Task.WhenAll
                (
                    jmContext.QueryFromSql<ElasticIndexAssociatedProductEntity>("Exec SP_GetAssociatedProductsForElastic", pProductIds).ToList()
                    .Select(x => x.ToAssociatedIndexModel(imageUrlPrefix)).ToList()
                );
            return associatedToIndex;
        }

        private static async Task<ElasticIndexAssociatedProduct> ToAssociatedIndexModel(this ElasticIndexAssociatedProductEntity model, string imageUrlPrefix)
        {
            return await Task.Run(() => new ElasticIndexAssociatedProduct
            {
                ProductId = model.ProductId,
                PartNumber = model.PartNumber,
                Name = model.Name ?? string.Empty,
                MetaKeywords = model.MetaKeywords ?? string.Empty,
                MetaDescription = model.MetaDescription ?? string.Empty,
                MetaTitle = model.MetaTitle ?? string.Empty,
                LimitedToStores = model.LimitedToStores,
                AvailableStores = !string.IsNullOrEmpty(model.AvailableStores) ? model.AvailableStores.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(i => Convert.ToInt32(i)).ToList() : null,
                ShortDescription = model.ShortDescription ?? string.Empty,
                FullDescription = model.FullDescription ?? string.Empty,
                SeName = model.SeName ?? string.Empty,
                StockAvailability = model.StockAvailability,
                DeliveryDateId = model.DeliveryDateId,
                DeliveryDateName = model.DeliveryDateName ?? string.Empty,
                CategoryName = model.CategoryName ?? string.Empty,
                CategoryId = model.CategoryId,
                CategoryIdsLimitToStore = !string.IsNullOrEmpty(model.CategoryIdsLimitToStore) ? model.CategoryIdsLimitToStore.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(i => Convert.ToInt32(i)).ToList() : null,
                CategoryParentNamesStr = model.CategoryParentNamesStr ?? string.Empty,
                CategoryIds = !string.IsNullOrEmpty(model.CategoryIdsStr) ? model.CategoryIdsStr.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(i => Convert.ToInt32(i)).ToList() : null,
                CategoryIdsStr = model.CategoryIdsStr ?? string.Empty,
                IsPublishedCategory = model.IsPublishedCategory,
                ManufacturerNumber = model.ManufacturerNumber ?? string.Empty,
                ManufacturerName = model.ManufacturerName ?? string.Empty,
                ManufacturerId = model.ManufacturerId,
                ManufacturerLimitToStore = model.ManufacturerLimitToStore,
                IsPublishedManufacturer = model.IsPublishedManufacturer,
                Price = model.Price,
                VendorName = model.VendorName ?? string.Empty,
                ProductPictureUrl = model.HasImage ? (imageUrlPrefix + model.ProductPictureUrl) : string.Empty,
                HasImage = model.HasImage,
                Specification = model.Specification ?? string.Empty
            }); ;;
        }
    }

Это метод загрузки.

public IList<ElasticIndexGroupProduct> IndexGroupProducts(int[] groupProductIds)
        {
            try
            {
                if (groupProductIds == null)
                    return null;

                var indexName = string.Format(_config.ElasticIndexName, _config.HostingEnvironment);
                var indexingGroupProductQueue = _searchEngineData.GetElasticGroupProducts(groupProductIds).GetAwaiter().GetResult().ToList();

                // Delete existing records
                _client.DeleteByQuery<ElasticIndexGroupProduct>(d => d.Index(indexName).Query(q => q.Bool(bq => bq.Filter(fq => fq.Terms(t => t.Field(f => f.ProductId).Terms(indexingGroupProductQueue.Select(x => x.ProductId).ToArray()))))));

                // Add records                
                var runningUpsertProductCount = 0;
                do
                {
                    var productsSubset = indexingGroupProductQueue.Skip(runningUpsertProductCount).Take(1000);
                    runningUpsertProductCount += 1000;

                    var descriptor = new BulkDescriptor();
                    productsSubset.ForEach(doc =>
                    {
                        descriptor.Index(indexName).Update<ElasticIndexGroupProduct>(u => u.Id(doc.Id).Doc(doc).Upsert(doc));
                    });
                    var upsertRespose = _client.Bulk(descriptor);
                    if (upsertRespose.ApiCall.Success)
                    {
                          productsSubset.ForEach(proupProduct =>
                          {
                              _jmProductService.UpdateElasticSearchIndexingDate(proupProduct.ProductId);
                              proupProduct.AssociatedProducts.ForEach(simpleProduct =>
                              {                                
                                 _jmProductService.UpdateElasticSearchIndexingDate(proupProduct.ProductId);
                              });
                          });
                    }
                } while (runningUpsertProductCount < indexingGroupProductQueue.Count);

                return indexingGroupProductQueue;
            }
            catch (Exception e)
            {
                _logger.Error($"Error - ElasticSearch Product Indexing", e);
                throw;
            }
        }
...