コード例 #1
0
        /// <summary>
        /// Swaps alias for culture
        /// </summary>
        /// <param name="language"></param>
        /// <param name="oldAlias"></param>
        /// <param name="newAlias"></param>
        public void SwitchAlias(CultureInfo language, string oldAlias, string newAlias)
        {
            lock (this)
            {
                var cultureInfo = language ?? CultureInfo.CurrentUICulture;
                VulcanHelper.GuardForNullAlias(ref oldAlias);
                VulcanHelper.GuardForNullAlias(ref newAlias);

                var client = CreateElasticClient(CommonConnectionSettings.ConnectionSettings); // use a raw elasticclient because we just need this to be quick

                var oldFullAlias = VulcanHelper.GetAliasName(Index, cultureInfo, oldAlias);
                var newFullAlias = VulcanHelper.GetAliasName(Index, cultureInfo, newAlias);

                var oldIndex = client.GetAlias(a => a.Name(oldFullAlias)).Indices?.First().Key;
                var newIndex = client.GetAlias(a => a.Name(newFullAlias)).Indices?.First().Key;

                client.Alias(bad => bad.Remove(a => a.Alias(oldFullAlias).Index("*"))
                             .Remove(a => a.Alias(newFullAlias).Index("*"))
                             .Add(a => a.Alias(oldFullAlias).Index(newIndex))
                             .Add(a => a.Alias(newFullAlias).Index(oldIndex)));

                client.Refresh("*");

                Clients?.Clear(); // force a client refresh
            }
        }
コード例 #2
0
        /// <summary>
        /// Search for content
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="searchDescriptor"></param>
        /// <param name="includeNeutralLanguage"></param>
        /// <param name="rootReferences"></param>
        /// <param name="typeFilter"></param>
        /// <param name="principleReadFilter"></param>
        /// <returns></returns>
        public virtual ISearchResponse <IContent> SearchContent <T>(
            Func <SearchDescriptor <T>, SearchDescriptor <T> > searchDescriptor = null,
            bool includeNeutralLanguage = false,
            IEnumerable <ContentReference> rootReferences = null,
            IEnumerable <Type> typeFilter  = null,
            IPrincipal principleReadFilter = null) where T : class, IContent
        {
            var resolvedDescriptor = searchDescriptor == null ? new SearchDescriptor <T>() : searchDescriptor.Invoke(new SearchDescriptor <T>());

            typeFilter         = typeFilter ?? typeof(T).GetSearchTypesFor(VulcanFieldConstants.AbstractFilter);
            resolvedDescriptor = resolvedDescriptor.Type(string.Join(",", typeFilter.Select(t => t.FullName)))
                                 .ConcreteTypeSelector((d, docType) => typeof(VulcanContentHit));

            var indexName = IndexName;

            if (!Language.Equals(CultureInfo.InvariantCulture) && includeNeutralLanguage)
            {
                indexName += "," + VulcanHelper.GetAliasName(VulcanHandler.Index, CultureInfo.InvariantCulture, IndexAlias);
            }

            resolvedDescriptor = resolvedDescriptor.Index(indexName);
            var validRootReferences = rootReferences?.Where(x => !ContentReference.IsNullOrEmpty(x)).ToList();
            var filters             = new List <QueryContainer>();

            if (validRootReferences?.Count > 0)
            {
                var scopeDescriptor = new QueryContainerDescriptor <T>().
                                      Terms(t => t.Field(VulcanFieldConstants.Ancestors).Terms(validRootReferences.Select(x => x.ToReferenceWithoutVersion().ToString())));

                filters.Add(scopeDescriptor);
            }

            if (principleReadFilter != null)
            {
                var permissionDescriptor = new QueryContainerDescriptor <T>().
                                           Terms(t => t.Field(VulcanFieldConstants.ReadPermission).Terms(principleReadFilter.GetRoles()));

                filters.Add(permissionDescriptor);
            }

            if (filters.Count > 0)
            {
                var descriptor = resolvedDescriptor;
                Func <SearchDescriptor <T>, ISearchRequest> selector = ts => descriptor;
                var container = selector.Invoke(new SearchDescriptor <T>());

                if (container.Query != null)
                {
                    filters.Insert(0, container.Query);
                }

                resolvedDescriptor = resolvedDescriptor.Query(q => q.Bool(b => b.Must(filters.ToArray())));
            }

            var response = Search <T, IContent>(resolvedDescriptor);

            return(response);
        }
コード例 #3
0
 /// <summary>
 /// DI Constructor
 /// </summary>
 /// <param name="index"></param>
 /// <param name="indexAlias"></param>
 /// <param name="settings"></param>
 /// <param name="language"></param>
 /// <param name="contentLoader"></param>
 /// <param name="vulcanHandler"></param>
 /// <param name="vulcanPipelineSelector"></param>
 public VulcanClient
 (
     string index,
     string indexAlias,
     IConnectionSettingsValues settings,
     CultureInfo language,
     IContentLoader contentLoader,
     IVulcanHandler vulcanHandler,
     IVulcanPipelineSelector vulcanPipelineSelector) : base(settings)
 {
     Language                = language ?? throw new Exception("Vulcan client requires a language (you may use CultureInfo.InvariantCulture if needed for non-language specific data)");
     IndexName               = VulcanHelper.GetAliasName(index, language, indexAlias);
     IndexAlias              = indexAlias;
     ContentLoader           = contentLoader;
     VulcanHandler           = vulcanHandler;
     _vulcanPipelineSelector = vulcanPipelineSelector;
 }
コード例 #4
0
        /// <summary>
        /// Get a Vulcan client
        /// </summary>
        /// <param name="language">Pass in null for current culture, a specific culture or CultureInfo.InvariantCulture to get a client for non-language specific data</param>
        /// <param name="alias"></param>
        /// <returns>A Vulcan client</returns>
        public virtual IVulcanClient GetClient(CultureInfo language = null, string alias = null)
        {
            var           cultureInfo = language ?? CultureInfo.CurrentUICulture;
            var           aliasSafe   = string.IsNullOrWhiteSpace(alias) ? VulcanHelper.MasterAlias : alias;
            IVulcanClient storedClient;

            lock (_lockObject)
            {
                if (!Clients.ContainsKey(aliasSafe))
                {
                    Clients[aliasSafe] = new ConcurrentDictionary <CultureInfo, IVulcanClient>();
                }
                if (Clients[aliasSafe].TryGetValue(cultureInfo, out storedClient))
                {
                    return(storedClient);
                }

                // todo: need some sort of check here to make sure we still need to create a client
                var aliasName = VulcanHelper.GetAliasName(Index, cultureInfo, alias);
                var settings  = CommonConnectionSettings.ConnectionSettings;
                settings.InferMappingFor <ContentMixin>(pd => pd.Ignore(p => p.MixinInstance));
                settings.DefaultIndex(aliasName);

                var client    = CreateVulcanClient(Index, alias, settings, cultureInfo);
                var nodesInfo = client.NodesInfo(); // first let's check our version

                if (nodesInfo?.Nodes?.Any() != true)
                {
                    throw new Exception("Could not get Nodes info to check Elasticsearch Version. Check that you are correctly connected to Elasticsearch?");
                }

                var node = nodesInfo.Nodes.First();                // just use first

                if (string.IsNullOrWhiteSpace(node.Value.Version)) // just use first
                {
                    throw new Exception("Could not find a version on node to check Elasticsearch Version. Check that you are correctly connected to Elasticsearch?");
                }

                if (node.Value.Version.StartsWith("1."))
                {
                    throw new Exception("Sorry, Vulcan only works with Elasticsearch version 2.x or higher. The Elasticsearch node you are currently connected to is version " + node.Value.Version);
                }

                client.RunCustomIndexTemplates(Index, Logger);

                // keep our base last with lowest possible Order

#if NEST2
                client.PutIndexTemplate($"{Index}_analyzer_disabling", ad => ad
                                        .Order(0)
                                        .Template($"{Index}*") //match on all created indices for index name
                                        .Mappings(mappings => mappings.Map("_default_", map => map.DynamicTemplates(
                                                                               dyn => dyn.DynamicTemplate("analyzer_template", dt => dt
                                                                                                          .Match("*")                 //matches all fields
                                                                                                          .MatchMappingType("string") //that are a string
                                                                                                          .Mapping(dynmap => dynmap.String(s => s
                                                                                                                                           .NotAnalyzed()
                                                                                                                                           .IgnoreAbove(CreateIndexCustomizer.IgnoreAbove) // needed for: document contains at least one immense term in field
                                                                                                                                           .IncludeInAll(false)
                                                                                                                                           .Fields(f => f
                                                                                                                                                   .String(ana => ana
                                                                                                                                                           .Name(VulcanFieldConstants.AnalyzedModifier)
                                                                                                                                                           .IncludeInAll(false)
                                                                                                                                                           .Store()
                                                                                                                                                           )
                                                                                                                                                   ))
                                                                                                                   )
                                                                                                          )))));
#elif NEST5
                // note: strings are no more in ES5, for not analyzed text use Keyword and for analyzed use Text
                client.PutIndexTemplate($"{Index}_analyzer_disabling", ad => ad
                                        .Order(0)
                                        .Template($"{Index}*") //match on all created indices for index name
                                        .Mappings(mappings => mappings.Map("_default_", map => map.DynamicTemplates(
                                                                               dyn => dyn.DynamicTemplate("analyzer_template", dt => dt
                                                                                                          .Match("*")                                                                       //matches all fields
                                                                                                          .MatchMappingType("string")                                                       //that are a string
                                                                                                          .Mapping(dynmap => dynmap.Keyword(s => s
                                                                                                                                            .IgnoreAbove(CreateIndexCustomizer.IgnoreAbove) // needed for: document contains at least one immense term in field
                                                                                                                                            .Fields(f => f
                                                                                                                                                    .Text(ana => ana
                                                                                                                                                          .Name(VulcanFieldConstants.AnalyzedModifier)
                                                                                                                                                          .Store()
                                                                                                                                                          )
                                                                                                                                                    ))
                                                                                                                   )
                                                                                                          )))));
#endif
                string actualIndexName = null;

                if (client.AliasExists(a => a.Name(aliasName)).Exists)
                {
                    var indices = client.GetAlias(a => a.Name(aliasName)).Indices;

                    if (indices != null)
                    {
                        if (indices.Any())
                        {
                            actualIndexName = indices.First().Key;
                        }
                    }
                }

                if (actualIndexName == null)
                {
                    actualIndexName = VulcanHelper.GetRawIndexName(Index, cultureInfo);
                    var response = client.CreateIndex(actualIndexName, CreateIndexCustomizer.CustomizeIndex);

                    if (!response.IsValid)
                    {
                        Logger.Error("Could not create index " + actualIndexName + ": " + response.DebugInformation);
                    }
                    else
                    {
                        // set up the indexAlias
                        client.PutAlias(actualIndexName, aliasName);
                    }
                }

                client.Refresh(actualIndexName);
                var closeResponse = client.CloseIndex(actualIndexName);

                if (!closeResponse.IsValid)
                {
                    Logger.Error("Could not close index " + actualIndexName + ": " + closeResponse.DebugInformation);
                }

                InitializeAnalyzer(client);

                // run installers
                foreach (var installer in _vulcanPipelineInstallers)
                {
                    installer.Install(client);
                }

                // allows for customizations
                client.RunCustomizers(Logger);
                client.RunCustomMappers(Logger);

                client.OpenIndex(actualIndexName);

                if (CreateIndexCustomizer.WaitForActiveShards > 0)
                {
                    // Init shards to attempt to fix empty results on first request
                    client.ClusterHealth(x => x.WaitForActiveShards(
#if NEST2
                                             CreateIndexCustomizer.WaitForActiveShards
#elif NEST5
                                             CreateIndexCustomizer.WaitForActiveShards.ToString()
#endif
                                             ));
                }

                storedClient = client;
            }

            // ReSharper disable once InconsistentlySynchronizedField
            Clients[aliasSafe][cultureInfo] = storedClient;

            return(storedClient);
        }