|
@@ -7,7 +7,7 @@ using XF.Domain.Repository;
|
|
|
namespace Hotline.Repository.SqlSugar.Ts;
|
|
|
|
|
|
public class BaseRepositoryTextSearch<TEntity> : IRepositoryTextSearch<TEntity>
|
|
|
- where TEntity : class, IEntity<string>, ITextSearch, new()
|
|
|
+ where TEntity : class, ITextSearch, new()
|
|
|
{
|
|
|
private readonly ISugarUnitOfWork<HotlineDbContext> _uow;
|
|
|
private readonly ISqlSugarClient _db;
|
|
@@ -26,32 +26,28 @@ public class BaseRepositoryTextSearch<TEntity> : IRepositoryTextSearch<TEntity>
|
|
|
/// <param name="texts"></param>
|
|
|
/// <param name="cancellationToken"></param>
|
|
|
/// <returns></returns>
|
|
|
- public Task AddVectorAsync(string id, DateTime creationTime, ICollection<string> texts, CancellationToken cancellationToken)
|
|
|
+ public async Task AddVectorAsync(string id, DateTime creationTime, ICollection<string> texts, CancellationToken cancellationToken)
|
|
|
{
|
|
|
var weights = texts.Select(d => new NpgsqlWeight
|
|
|
{
|
|
|
Text = d
|
|
|
}).ToList();
|
|
|
- return AddVectorAsync(id, creationTime, weights, cancellationToken);
|
|
|
- }
|
|
|
|
|
|
- /// <summary>
|
|
|
- /// 自定义权重
|
|
|
- /// </summary>
|
|
|
- /// <param name="id">原始数据Id</param>
|
|
|
- /// <param name="creationTime">原始数据CreationTime</param>
|
|
|
- /// <param name="cancellationToken"></param>
|
|
|
- /// <returns></returns>
|
|
|
- public async Task AddVectorAsync(string id, DateTime creationTime, ICollection<NpgsqlWeight> weights, CancellationToken cancellationToken)
|
|
|
- {
|
|
|
var tableName = typeof(TEntity).Name.ToSnakeCase();
|
|
|
var vectorSql = CreateVectorSql(weights);
|
|
|
- var sql = $"INSERT INTO @tableName VALUES ('@id', '@creationTime', @vector)";
|
|
|
- await _db.Ado.ExecuteCommandAsync(sql, new { tableName, id, creationTime, vector = vectorSql }, cancellationToken);
|
|
|
+ var vectorTexts = JsonSerializer.Serialize(texts);
|
|
|
+ var sql = $"INSERT INTO {tableName} (\"Id\",\"Vector\",\"VectorTexts\",\"CreationTime\") VALUES ('{id}', {vectorSql}, '{vectorTexts}'::json, '{creationTime}')";
|
|
|
+ await _db.Ado.ExecuteCommandAsync(sql, null, cancellationToken);
|
|
|
/*
|
|
|
- INSERT INTO "order_ts" VALUES ('f595e730-909a-45e4-9138-a84bf15f4660', '2023-09-06 10:51:38', setweight(to_tsvector('simple', 'aa'), 'C') || setweight(to_tsvector('simple', 'bb'), 'C'))
|
|
|
- */
|
|
|
-
|
|
|
+ INSERT INTO "order_ts"
|
|
|
+("Id","Vector","VectorTexts","CreationTime")
|
|
|
+VALUES ('f595e730-909a-45e4-9138-a84bf15f4661',
|
|
|
+setweight(to_tsvector('simple', 'cc'), 'C') ||
|
|
|
+setweight(to_tsvector('simple', 'bb'), 'C'),
|
|
|
+'["cc","bb"]'
|
|
|
+, '2023-09-06 10:51:39'
|
|
|
+)
|
|
|
+ */
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
@@ -66,26 +62,30 @@ public class BaseRepositoryTextSearch<TEntity> : IRepositoryTextSearch<TEntity>
|
|
|
|
|
|
var tableName = typeof(TEntity).Name.ToSnakeCase();
|
|
|
var vectorSql = CreateVectorSql(weights);
|
|
|
-
|
|
|
- var sql = $"UPDATE @tableName SET \"Vector\"=@vector, \"VectorTexts\"=@vectorTexts WHERE id=@id ";
|
|
|
var vectorTexts = JsonSerializer.Serialize(texts);
|
|
|
- await _db.Ado.ExecuteCommandAsync(sql, new { tableName, id, vector = vectorSql, vectorTexts }, cancellationToken);
|
|
|
+ var sql = $"UPDATE {tableName} SET \"Vector\"={vectorSql}, \"VectorTexts\"='{vectorTexts}'::json WHERE \"Id\"=@id ";
|
|
|
+ await _db.Ado.ExecuteCommandAsync(sql, new { id }, cancellationToken);
|
|
|
}
|
|
|
|
|
|
- public async Task<List<RankedResult<TEntity>>> SearchAsync(IReadOnlyList<string> texts, CancellationToken cancellationToken)
|
|
|
+ public async Task<List<TEntity>> SearchAsync(IReadOnlyList<string> texts, CancellationToken cancellationToken)
|
|
|
{
|
|
|
var tableName = typeof(TEntity).Name.ToSnakeCase();
|
|
|
- var tsquery = string.Join(' ', texts);
|
|
|
- var sql = "SELECT Id, CreationTime, Vector, Texts, ts_rank(\"Vector\", query) AS score FROM @tableName to_tsquery('simple', @tsquery) query WHERE \"Vector\" @@ query ORDER BY score DESC)";
|
|
|
- return await _db.Ado.SqlQueryAsync<RankedResult<TEntity>>(sql, new { tableName, tsquery }, cancellationToken);
|
|
|
- }
|
|
|
-
|
|
|
+ var tsquery = string.Join('|', texts);
|
|
|
+ var sql =
|
|
|
+ $"SELECT \"Id\", \"Vector\", \"VectorTexts\", \"CreationTime\", ts_rank(\"Vector\", query) AS score FROM {tableName}, to_tsquery('simple', '{tsquery}') query WHERE \"Vector\" @@ query ORDER BY score DESC";
|
|
|
+ return await _db.Ado.SqlQueryAsync<TEntity>(sql, null, cancellationToken);
|
|
|
|
|
|
+ /*
|
|
|
+ SELECT "Id", "Vector", "VectorTexts", "CreationTime", ts_rank("Vector", query) AS score
|
|
|
+FROM order_ts, to_tsquery('simple', 'bb') query WHERE "Vector" @@ query ORDER BY score DESC
|
|
|
+ */
|
|
|
+ }
|
|
|
+
|
|
|
#region private method
|
|
|
|
|
|
private static string CreateVectorSql(ICollection<NpgsqlWeight> weights)
|
|
|
{
|
|
|
- var setweghtStrings = weights.Select(d => $"setweight(to_tsvector('simple', {d.Text}), '{d.Weight}')");
|
|
|
+ var setweghtStrings = weights.Select(d => $"setweight(to_tsvector('simple', '{d.Text}'), '{d.Weight}')");
|
|
|
var vectorString = string.Join(" || ", setweghtStrings);
|
|
|
return vectorString;
|
|
|
}
|