Я получил до получения оценки с использованием метода сходства, который я зарегистрировал в качестве функции DB в DBContext и и Сравнение его с порогом, но эта реализация является просто истинным/ложным фильтром для результатов, а не для динамического поиска, который я хочу.
Моя текущая реализация выглядит так (только один тип Атм, но я думаю, что я мог бы сделать его глобальным и удалить переключатель): < /p>
Код: Выделить всё
public class ExperimentalSearchBinder : QueryBinder, ISearchBinder
{
public Expression BindSearch(SearchClause searchClause, QueryBinderContext context)
{
var parameter = Expression.Parameter(context.ElementClrType, "p");
if (searchClause.Expression is not SearchTermNode node) throw new Exception("Only simple search clauses are allowed");
switch (context.ElementClrType)
{
case { } clrType when clrType == typeof(ComponentModel):
var properties = typeof(ComponentModel).GetProperties()
.Where(p => p.PropertyType == typeof(string) || p.PropertyType == typeof(Guid))
.ToList();
Expression? combinedExpression = null;
foreach (var propertyInfo in properties)
{
Expression property = Expression.Property(parameter, propertyInfo.Name);
if (propertyInfo.PropertyType == typeof(Guid))
{
property = Expression.Call(property, typeof(Guid).GetMethod("ToString", Type.EmptyTypes)!);
}
var method = typeof(DatabaseContext).GetMethod(nameof(DatabaseContext.Similarity), [typeof(string), typeof(string)]);
if (method is null)
{
throw new MissingMethodException($"Method not found: {nameof(DatabaseContext.Similarity)}");
}
var searchTerm = Expression.Constant(node.Text);
var similarityCall = Expression.Call(method, property, searchTerm);
var comparison = Expression.GreaterThanOrEqual(similarityCall, Expression.Constant(0.1));
combinedExpression = combinedExpression == null ? comparison : Expression.OrElse(combinedExpression, comparison);
}
if (combinedExpression is null)
{
throw new Exception("Failed to build combinedExpression");
}
return Expression.Lambda(combinedExpression, parameter);
default:
//Default simply tries to match ID
//TODO: Make a better default implementation
var defaultProperty = Expression.Property(parameter, "Id");
var defaultSearchTerm = Expression.Constant(node.Text);
var defaultComparison = Expression.Equal(defaultProperty, defaultSearchTerm);
return Expression.Lambda(defaultComparison, parameter);
}
}
}
< /code>
Для реализации сортировки я бы в идеале хотел бы, чтобы SQL выглядел примерно так: < /p>
SELECT *
FROM (
SELECT *, SIMILARITY(name, '801') + similarity(description, '801') as Score
FROM component
) subquery
WHERE Score > 0.3 order by Score desc;
Подробнее здесь: https://stackoverflow.com/questions/793 ... in-asp-net
Мобильная версия