From ddda353df5fff31d9d411b5a65530e2e120f2985 Mon Sep 17 00:00:00 2001 From: colin Date: Fri, 21 Aug 2026 11:58:28 +0800 Subject: [PATCH] feat: Add the ESQL testing module --- aspnet-core/LINGYUN.MicroService.All.slnx | 1 + .../FodyWeavers.xml | 3 ++ .../FodyWeavers.xsd | 30 +++++++++++++++++++ .../EsqlQuery/EsqlExpressionQueryService.cs | 27 +++++++++++++++-- .../README.md | 22 ++++++++++++++ ...N.Abp.Elasticsearch.EsqlQuery.Tests.csproj | 20 +++++++++++++ .../AbpElasticsearchEsqlQueryTestBase.cs | 7 +++++ .../AbpElasticsearchEsqlQueryTestModule.cs | 21 +++++++++++++ .../EsqlExpressionQueryService_Tests.cs | 5 ++++ 9 files changed, 134 insertions(+), 2 deletions(-) create mode 100644 aspnet-core/framework/elasticsearch/LINGYUN.Abp.Elasticsearch.EsqlQuery/FodyWeavers.xml create mode 100644 aspnet-core/framework/elasticsearch/LINGYUN.Abp.Elasticsearch.EsqlQuery/FodyWeavers.xsd create mode 100644 aspnet-core/framework/elasticsearch/LINGYUN.Abp.Elasticsearch.EsqlQuery/README.md create mode 100644 aspnet-core/tests/LINGYUN.Abp.Elasticsearch.EsqlQuery.Tests/LINGYUN.Abp.Elasticsearch.EsqlQuery.Tests.csproj create mode 100644 aspnet-core/tests/LINGYUN.Abp.Elasticsearch.EsqlQuery.Tests/LINGYUN/Abp/Elasticsearch/EsqlQuery/AbpElasticsearchEsqlQueryTestBase.cs create mode 100644 aspnet-core/tests/LINGYUN.Abp.Elasticsearch.EsqlQuery.Tests/LINGYUN/Abp/Elasticsearch/EsqlQuery/AbpElasticsearchEsqlQueryTestModule.cs create mode 100644 aspnet-core/tests/LINGYUN.Abp.Elasticsearch.EsqlQuery.Tests/LINGYUN/Abp/Elasticsearch/EsqlQuery/EsqlExpressionQueryService_Tests.cs diff --git a/aspnet-core/LINGYUN.MicroService.All.slnx b/aspnet-core/LINGYUN.MicroService.All.slnx index 7b6d3d7a1..ea3848ab4 100644 --- a/aspnet-core/LINGYUN.MicroService.All.slnx +++ b/aspnet-core/LINGYUN.MicroService.All.slnx @@ -530,6 +530,7 @@ + diff --git a/aspnet-core/framework/elasticsearch/LINGYUN.Abp.Elasticsearch.EsqlQuery/FodyWeavers.xml b/aspnet-core/framework/elasticsearch/LINGYUN.Abp.Elasticsearch.EsqlQuery/FodyWeavers.xml new file mode 100644 index 000000000..1715698cc --- /dev/null +++ b/aspnet-core/framework/elasticsearch/LINGYUN.Abp.Elasticsearch.EsqlQuery/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/aspnet-core/framework/elasticsearch/LINGYUN.Abp.Elasticsearch.EsqlQuery/FodyWeavers.xsd b/aspnet-core/framework/elasticsearch/LINGYUN.Abp.Elasticsearch.EsqlQuery/FodyWeavers.xsd new file mode 100644 index 000000000..3f3946e28 --- /dev/null +++ b/aspnet-core/framework/elasticsearch/LINGYUN.Abp.Elasticsearch.EsqlQuery/FodyWeavers.xsd @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. + + + + + A comma-separated list of error codes that can be safely ignored in assembly verification. + + + + + 'false' to turn off automatic generation of the XML Schema file. + + + + + \ No newline at end of file diff --git a/aspnet-core/framework/elasticsearch/LINGYUN.Abp.Elasticsearch.EsqlQuery/LINGYUN/Abp/Elasticsearch/EsqlQuery/EsqlExpressionQueryService.cs b/aspnet-core/framework/elasticsearch/LINGYUN.Abp.Elasticsearch.EsqlQuery/LINGYUN/Abp/Elasticsearch/EsqlQuery/EsqlExpressionQueryService.cs index 6d22f25b8..231fd2379 100644 --- a/aspnet-core/framework/elasticsearch/LINGYUN.Abp.Elasticsearch.EsqlQuery/LINGYUN/Abp/Elasticsearch/EsqlQuery/EsqlExpressionQueryService.cs +++ b/aspnet-core/framework/elasticsearch/LINGYUN.Abp.Elasticsearch.EsqlQuery/LINGYUN/Abp/Elasticsearch/EsqlQuery/EsqlExpressionQueryService.cs @@ -11,6 +11,15 @@ using Volo.Abp.DependencyInjection; namespace LINGYUN.Abp.Elasticsearch.EsqlQuery; +/// +/// NOTE: The tests for methods like Contains in the collection have failed. Please do not use this interface for collection filtering. +/// TODO: According to the official documentation, is it feasible? Is the support for nested types not available? +/// See: https://www.elastic.co/docs/reference/elasticsearch/clients/dotnet/linq-to-esql#linq-esql-filtering +/// var brands = new[] { "TechCorp", "StyleMax", "HomeBase" }; +/// client.Esql.Query(q => q.Where(p => brands.Contains(p.Brand))); +/// → WHERE brand IN ("TechCorp", "StyleMax", "HomeBase") +/// + [Dependency(ReplaceServices = true)] public class EsqlExpressionQueryService : ExpressionQueryService, ITransientDependency { @@ -29,6 +38,7 @@ public class EsqlExpressionQueryService : ExpressionQueryService, ITransientDepe var client = ClientFactory.Create(); return await client.Esql.CreateQuery() + .From(indexName) .Where(expression) .AsEsqlQueryable() .CountAsync(cancellationToken); @@ -42,18 +52,31 @@ public class EsqlExpressionQueryService : ExpressionQueryService, ITransientDepe int skipCount = 0, Fields? sourceExcludes = null, Fields? sourceIncludes = null, + object[]? beginMarker = null, CancellationToken cancellationToken = default) where TDocument : class { var client = ClientFactory.Create(); - var query = client.Esql.CreateQuery().Where(expression); + var query = client.Esql.CreateQuery() + .From(indexName) + .Where(expression); if (!sorting.IsNullOrWhiteSpace()) { query = query.OrderBy(sorting); } + if (sourceExcludes != null) + { + query = query.Drop(sourceExcludes.Select(f => f.Name!).ToArray()); + } + if (sourceIncludes != null) + { + query = query.Keep(sourceIncludes.Select(f => f.Name!).ToArray()); + } + // TODO: 需要构建范围过滤条件,加入到query中以实现分页查询 + // See: https://www.elastic.co/docs/reference/elasticsearch/clients/dotnet/linq-to-esql#linq-esql-sorting return await query - .PageBy(skipCount, maxResultCount) + .Take(maxResultCount) .AsEsqlQueryable() .ToListAsync(cancellationToken); } diff --git a/aspnet-core/framework/elasticsearch/LINGYUN.Abp.Elasticsearch.EsqlQuery/README.md b/aspnet-core/framework/elasticsearch/LINGYUN.Abp.Elasticsearch.EsqlQuery/README.md new file mode 100644 index 000000000..1af512617 --- /dev/null +++ b/aspnet-core/framework/elasticsearch/LINGYUN.Abp.Elasticsearch.EsqlQuery/README.md @@ -0,0 +1,22 @@ +# LINGYUN.Abp.Elasticsearch.EsqlQuery + +[IExpressionQueryService](../LINGYUN.Abp.Elasticsearch/LINGYUN/Abp/Elasticsearch/IExpressionQueryService.cs) 的ES|QL查询集成. + +**注意**: +* 使用 ES|QL 查询方案不能进行深度分页,数据条目超出10000时依旧存在ES分页限制. +如需支持深度分页,请使用默认 [ExpressionQueryService](../LINGYUN.Abp.Elasticsearch/LINGYUN/Abp/Elasticsearch/ExpressionQueryService.cs) `search_after` 方案 + +* 不支持使用 由于ES|QL不支持 `Skip`, 暂不支持分页查询 + +* 对于嵌套类型的集合方法测试未通过,请勿使用集合的过滤条件 + + +## 模块引用 + +```csharp +[DependsOn(typeof(AbpElasticsearchEsqlQueryModule))] +public class YouProjectModule : AbpModule +{ + // other +} +``` diff --git a/aspnet-core/tests/LINGYUN.Abp.Elasticsearch.EsqlQuery.Tests/LINGYUN.Abp.Elasticsearch.EsqlQuery.Tests.csproj b/aspnet-core/tests/LINGYUN.Abp.Elasticsearch.EsqlQuery.Tests/LINGYUN.Abp.Elasticsearch.EsqlQuery.Tests.csproj new file mode 100644 index 000000000..abf270749 --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.Elasticsearch.EsqlQuery.Tests/LINGYUN.Abp.Elasticsearch.EsqlQuery.Tests.csproj @@ -0,0 +1,20 @@ + + + + net10.0 + + false + AnyCPU + + + + + + + + + + + + + diff --git a/aspnet-core/tests/LINGYUN.Abp.Elasticsearch.EsqlQuery.Tests/LINGYUN/Abp/Elasticsearch/EsqlQuery/AbpElasticsearchEsqlQueryTestBase.cs b/aspnet-core/tests/LINGYUN.Abp.Elasticsearch.EsqlQuery.Tests/LINGYUN/Abp/Elasticsearch/EsqlQuery/AbpElasticsearchEsqlQueryTestBase.cs new file mode 100644 index 000000000..76c610667 --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.Elasticsearch.EsqlQuery.Tests/LINGYUN/Abp/Elasticsearch/EsqlQuery/AbpElasticsearchEsqlQueryTestBase.cs @@ -0,0 +1,7 @@ +using LINGYUN.Abp.Tests; + +namespace LINGYUN.Abp.Elasticsearch.EsqlQuery; + +public abstract class AbpElasticsearchEsqlQueryTestBase : AbpTestsBase +{ +} diff --git a/aspnet-core/tests/LINGYUN.Abp.Elasticsearch.EsqlQuery.Tests/LINGYUN/Abp/Elasticsearch/EsqlQuery/AbpElasticsearchEsqlQueryTestModule.cs b/aspnet-core/tests/LINGYUN.Abp.Elasticsearch.EsqlQuery.Tests/LINGYUN/Abp/Elasticsearch/EsqlQuery/AbpElasticsearchEsqlQueryTestModule.cs new file mode 100644 index 000000000..ef8ec6a55 --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.Elasticsearch.EsqlQuery.Tests/LINGYUN/Abp/Elasticsearch/EsqlQuery/AbpElasticsearchEsqlQueryTestModule.cs @@ -0,0 +1,21 @@ +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Modularity; + +namespace LINGYUN.Abp.Elasticsearch.EsqlQuery; + +[DependsOn( + typeof(AbpElasticsearchEsqlQueryModule), + typeof(AbpElasticsearchTestModule))] +public class AbpElasticsearchEsqlQueryTestModule : AbpModule +{ + private const string UserSecretsId = "D4327320-718E-4A7F-A987-85838EDD8675"; + + public override void PreConfigureServices(ServiceConfigurationContext context) + { + context.Services.ReplaceConfiguration(ConfigurationHelper.BuildConfiguration(builderAction: builder => + { + builder.AddUserSecrets(UserSecretsId); + })); + } +} diff --git a/aspnet-core/tests/LINGYUN.Abp.Elasticsearch.EsqlQuery.Tests/LINGYUN/Abp/Elasticsearch/EsqlQuery/EsqlExpressionQueryService_Tests.cs b/aspnet-core/tests/LINGYUN.Abp.Elasticsearch.EsqlQuery.Tests/LINGYUN/Abp/Elasticsearch/EsqlQuery/EsqlExpressionQueryService_Tests.cs new file mode 100644 index 000000000..f2caae7d1 --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.Elasticsearch.EsqlQuery.Tests/LINGYUN/Abp/Elasticsearch/EsqlQuery/EsqlExpressionQueryService_Tests.cs @@ -0,0 +1,5 @@ +namespace LINGYUN.Abp.Elasticsearch.EsqlQuery; + +public class EsqlExpressionQueryService_Tests : ExpressionQueryService_Tests +{ +}