示例#1
0
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="index"></param>
        /// <param name="settings"></param>
        /// <param name="language"></param>
        public VulcanClient(string index, ConnectionSettings settings, CultureInfo language)
            : base(settings)
        {
            if (language == null)
            {
                throw new Exception("Vulcan client requires a language (you may use CultureInfo.InvariantCulture if needed for non-language specific data)");
            }

            Language  = language;
            IndexName = VulcanHelper.GetIndexName(index, Language);
        }
示例#2
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>
        /// <returns>A Vulcan client</returns>
        public virtual IVulcanClient GetClient(CultureInfo language = null)
        {
            var cultureInfo = language ?? CultureInfo.CurrentUICulture;

            IVulcanClient storedClient;

            if (clients.TryGetValue(cultureInfo, out storedClient))
            {
                return(storedClient);
            }

            lock (lockObject)
            {
                // we now know what our culture is (current culture or invariant), but we need to choose the language analyzer
                var languageAnalyzer = VulcanHelper.GetAnalyzer(cultureInfo);
                var indexName        = VulcanHelper.GetIndexName(Index, cultureInfo);
                var settings         = CommonConnectionSettings.Service.ConnectionSettings;
                settings.InferMappingFor <ContentMixin>(pd => pd.Ignore(p => p.MixinInstance));
                settings.DefaultIndex(indexName);

                var client = CreateVulcanClient(Index, settings, cultureInfo);

                // first let's check our version
                var nodesInfo = client.NodesInfo();

                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?");
                }
                else
                {
                    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?");
                    }
                    else
                    {
                        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
                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.Service.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(true)
                                                                                                                                                           )
                                                                                                                                                   ))
                                                                                                                   )
                                                                                                          )))));

                if (!client.IndexExists(indexName).Exists)
                {
                    var response = client.CreateIndex(indexName, CreateIndexCustomizer.Service.CustomizeIndex);

                    if (!response.IsValid)
                    {
                        Logger.Error("Could not create index " + indexName + ": " + response.DebugInformation);
                    }
                }

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

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

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

                var openResponse = client.OpenIndex(indexName);
                var initShards   = client.ClusterHealth(x => x.WaitForActiveShards(CreateIndexCustomizer.Service.WaitForActiveShards)); // fixes empty results on first request

                clients.Add(cultureInfo, client);

                return(client);
            }
        }
示例#3
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
        {
            SearchDescriptor <T> resolvedDescriptor;

            if (searchDescriptor == null)
            {
                resolvedDescriptor = new SearchDescriptor <T>();
            }
            else
            {
                resolvedDescriptor = 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 != CultureInfo.InvariantCulture && includeNeutralLanguage)
            {
                indexName += "," + VulcanHelper.GetIndexName(VulcanHandler.Service.Index, CultureInfo.InvariantCulture);
            }

            resolvedDescriptor = resolvedDescriptor.Index(indexName);
            var validRootReferences       = rootReferences?.Where(x => !ContentReference.IsNullOrEmpty(x)).ToList();
            List <QueryContainer> 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)
            {
                Func <SearchDescriptor <T>, ISearchRequest> selector = ts => resolvedDescriptor;
                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 = base.Search <T, IContent>(resolvedDescriptor);

            return(response);
        }