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
+{
+}