/// <summary>
        /// Add mapping by string
        /// </summary>
        /// <param name="typeName"></param>
        public static void AddMapping(string typeName)
        {
            if (AddedMappings?.Contains(typeName) == true)
            {
                return;
            }

            try
            {
                IVulcanClient client   = ServiceLocator.Current.GetInstance <IVulcanHandler>().GetClient(CultureInfo.InvariantCulture);
                var           response = client.Map <object>(m => m.
                                                             Index("_all").
                                                             Type(typeName).
                                                             Properties(props => props.
                                                                        Attachment(s => s.Name(MediaContents)
                                                                                   .FileField(ff => ff.Name("content").Store().TermVector(Nest.TermVectorOption.WithPositionsOffsets))
                                                                                   ))
                                                             );

                if (!response.IsValid)
                {
                    throw new Exception(response.DebugInformation);
                }

                AddedMappings.Add(typeName);
            }
            catch (Exception ex)
            {
                _Logger.Error("Failed to map attachment field for type: " + typeName, ex);
            }
        }
        void IVulcanPipelineInstaller.Install(IVulcanClient client)
        {
            if (!_vulcanAttachmentIndexerSettings.EnableAttachmentPlugins || !client.Language.Equals(CultureInfo.InvariantCulture))
            {
                return;
            }
            var info = client.NodesInfo();

            if (info?.Nodes?.Any(x => x.Value?.Plugins?.Any(y => string.Compare(y.Name, PluginName, StringComparison.OrdinalIgnoreCase) == 0) == true) != true)
            {
                throw new Exception($"No attachment plugin found, be sure to install the '{PluginName}' plugin on your Elastic Search Server!");
            }

#if NEST2
            // v2, to do, get all MediaData types that are allowed and loop them
            var mediaDataTypes = Core.Extensions.TypeExtensions.GetSearchTypesFor <MediaData>(t => t.IsAbstract == false);

            foreach (var mediaType in mediaDataTypes)
            {
                var descriptors      = mediaType.GetCustomAttributes(false).OfType <MediaDescriptorAttribute>();
                var extensionStrings = string.Join(",", descriptors.Select(x => x.ExtensionString ?? ""));
                var extensions       = extensionStrings.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                var manualCheck      = MapAttachment?.Invoke(mediaType) ?? false;

                // only map ones we allow
                if (!extensions.Intersect(_vulcanAttachmentIndexerSettings.SupportedFileExtensions).Any() && !manualCheck)
                {
                    continue;
                }

                var response = client.Map <object>(m => m.
                                                   Index(client.IndexName). // was _all
                                                   Type(mediaType.FullName).
                                                   Properties(props => props.
                                                              Attachment(s => s.Name(MediaContents)
                                                                         .FileField(ff => ff.Name("content").Store().TermVector(Nest.TermVectorOption.WithPositionsOffsets))
                                                                         ))
                                                   );

                if (!response.IsValid)
                {
                    throw new Exception(response.DebugInformation);
                }
            }
#elif NEST5
// v5, use pipeline
            var response = client.PutPipeline(PipelineId, p => p
                                              .Description("Document attachment pipeline")
                                              .Processors(pr => pr
                                                          .Attachment <Nest.Attachment>(a => a
                                                                                        .Field(MediaContents)
                                                                                        .TargetField(MediaContents)
                                                                                        .IndexedCharacters(-1)
                                                                                        )
                                                          )
                                              );

            if (!response.IsValid)
            {
                throw new Exception(response.DebugInformation);
            }
#endif
        }