OrchardCMS / OrchardCore

Orchard Core is an open-source modular and multi-tenant application framework built with ASP.NET Core, and a content management system (CMS) built on top of that framework.
https://orchardcore.net
BSD 3-Clause "New" or "Revised" License
7.43k stars 2.4k forks source link

ElasticSearch services throw an exception while trying to search for related documents #16998

Open MikeAlhayek opened 2 days ago

MikeAlhayek commented 2 days ago

Describe the bug

When using Elasticsearch service, I am seeing the following in my logs

ElasticSearch services throw an exception while trying to search for related documents. Elasticsearch.Net.UnexpectedElasticsearchClientException: Index name is null for the given type and no default index is set. Map an index name using ConnectionSettings.DefaultMappingFor<TDocument>() or set a default index using ConnectionSettings.DefaultIndex().
 ---> System.ArgumentException: Index name is null for the given type and no default index is set. Map an index name using ConnectionSettings.DefaultMappingFor<TDocument>() or set a default index using ConnectionSettings.DefaultIndex().
   at Nest.IndexNameResolver.ValidateIndexName(String indexName)
   at Nest.IndexNameResolver.Resolve(Type type)
   at Nest.IndexNameResolver.Resolve(IndexName i)
   at Nest.IndexNameFormatter.Serialize(JsonWriter& writer, IndexName value, IJsonFormatterResolver formatterResolver)
   at Elasticsearch.Net.Nest_ILikeDocumentFormatter4.Serialize(JsonWriter&, ILikeDocument, IJsonFormatterResolver)
   at Nest.UnionFormatter`2.Serialize(JsonWriter& writer, Union`2 value, IJsonFormatterResolver formatterResolver)
   at Nest.LikeFormatter.Serialize(JsonWriter& writer, Like value, IJsonFormatterResolver formatterResolver)
   at Elasticsearch.Net.Utf8Json.Formatters.CollectionFormatterBase`4.Serialize(JsonWriter& writer, TCollection value, IJsonFormatterResolver formatterResolver)
   at Elasticsearch.Net.Nest_IMoreLikeThisQueryFormatter3.Serialize(JsonWriter&, IMoreLikeThisQuery, IJsonFormatterResolver)
   at Elasticsearch.Net.Nest_IQueryContainerFormatter2.Serialize(JsonWriter&, IQueryContainer, IJsonFormatterResolver)
   at Nest.QueryContainerInterfaceFormatter.Serialize(JsonWriter& writer, IQueryContainer value, IJsonFormatterResolver formatterResolver)
   at Nest.QueryContainerFormatter.Serialize(JsonWriter& writer, QueryContainer value, IJsonFormatterResolver formatterResolver)
   at Elasticsearch.Net.Nest_ISearchRequestFormatter1.Serialize(JsonWriter&, ISearchRequest, IJsonFormatterResolver)
   at Elasticsearch.Net.Utf8Json.JsonSerializer.SerializeAsync[T](Stream stream, T value, IJsonFormatterResolver resolver)
   at Elasticsearch.Net.SerializableData`1.WriteAsync(Stream writableStream, IConnectionConfigurationValues settings, CancellationToken cancellationToken)
   at Elasticsearch.Net.HttpConnection.SetContentAsync(HttpRequestMessage message, RequestData requestData, CancellationToken cancellationToken)
   at Elasticsearch.Net.HttpConnection.RequestAsync[TResponse](RequestData requestData, CancellationToken cancellationToken)
   at Elasticsearch.Net.RequestPipeline.CallElasticsearchAsync[TResponse](RequestData requestData, CancellationToken cancellationToken)
   at Elasticsearch.Net.Transport`1.RequestAsync[TResponse](HttpMethod method, String path, CancellationToken cancellationToken, PostData data, IRequestParameters requestParameters)
   --- End of inner exception stack trace ---
   at Elasticsearch.Net.Transport`1.RequestAsync[TResponse](HttpMethod method, String path, CancellationToken cancellationToken, PostData data, IRequestParameters requestParameters)
   at Nest.ElasticClient.SearchAsync[TDocument](ISearchRequest request, CancellationToken ct)
   at OrchardCore.Search.Elasticsearch.Core.Services.ElasticIndexManager.SearchAsync(String indexName, QueryContainer query, List`1 sort, Int32 from, Int32 size)
   at OrchardCore.Search.Elasticsearch.Core.Services.ElasticSearchQueryService.ExecuteQueryAsync(String indexName, QueryContainer query, List`1 sort, Int32 from, Int32 size)
   at CloudSolutions.Knowledges.Drivers.RelatedContentPartDisplayDriver.<>c__DisplayClass7_0.<<DisplayAsync>b__0>d.MoveNext() in /app/Modules/CloudSolutions.Knowledges/Drivers/RelatedContentPartDisplayDriver.cs:line 108    at Elasticsearch.Net.Transport`1.RequestAsync[TResponse](HttpMethod method, String path, CancellationToken cancellationToken, PostData data, IRequestParameters requestParameters)
   at Nest.ElasticClient.SearchAsync[TDocument](ISearchRequest request, CancellationToken ct)
   at OrchardCore.Search.Elasticsearch.Core.Services.ElasticIndexManager.SearchAsync(String indexName, QueryContainer query, List`1 sort, Int32 from, Int32 size)
   at OrchardCore.Search.Elasticsearch.Core.Services.ElasticSearchQueryService.ExecuteQueryAsync(String indexName, QueryContainer query, List`1 sort, Int32 from, Int32 size)

My RelatedContentDisplayDriver queries related documents like this

            try
            {
                var query = new MoreLikeThisQuery()
                {
                    Fields = searchSettings.DefaultSearchFields,
                    Analyzer = await _serviceProvider.GetRequiredService<ElasticIndexSettingsService>().GetQueryAnalyzerAsync(indexName),
                    Like =
                    [
                        new(new LikeDocument<ContentItem>(new Id(part.ContentItem.ContentItemId)))
                    ],
                    MinDocumentFrequency = settings.MinDocumentFrequency,
                    MaxDocumentFrequency = settings.MaxDocumentFrequency,
                    MinTermFrequency = settings.MinTermFrequency,
                    MaxQueryTerms = settings.MaxQueryTerms,
                    MinWordLength = settings.MinWordLength,
                    MaxWordLength = settings.MaxWordLength,
                };

                var contentItemIds = await searchQueryService.ExecuteQueryAsync(indexName, query, null, 0, 20);

                if (contentItemIds.Count > 0)
                {
                    var contentItems = await _session.Query<ContentItem, ContentItemIndex>()
                    .ListAsync();

                    model.ContentItems = contentItems.OrderBy(x => contentItemIds.IndexOf(x.ContentItemId))
                    .Take(settings.TotalVisible)
                    .ToArray();
                }
                else
                {
                    model.ContentItems = [];
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "ElasticSearch services throw an exception while trying to search for related documents.");
            }

I think there is an issue in the ElasticIndexManager.SearchAsync(indexName, query, sort, from, size)

Orchard Core version

1.x and 2.x

github-actions[bot] commented 6 hours ago

We triaged this issue and set the milestone according to the priority we think is appropriate (see the docs on how we triage and prioritize issues).

This indicates when the core team may start working on it. However, if you'd like to contribute, we'd warmly welcome you to do that anytime. See our guide on contributions here.