Skip to content

Commit

Permalink
RediSearch
Browse files Browse the repository at this point in the history
  • Loading branch information
2881099 committed Oct 25, 2024
1 parent 697f35b commit ea0b305
Show file tree
Hide file tree
Showing 4 changed files with 224 additions and 8 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ class TestDoc
public string Content { get; set; }

[FtTagField("tags")]
public string Tags { get; set; }
public string[] Tags { get; set; } //or string
[FtNumericField("views")]
public int Views { get; set; }
Expand All @@ -294,7 +294,7 @@ var list = repo.Search("*").InFields(a => new { a.Title }).ToList();
list = repo.Search("*").Return(a => new { a.Title, a.Tags }).ToList();
list = repo.Search("*").Return(a => new { tit1 = a.Title, tgs1 = a.Tags, a.Title, a.Tags }).ToList();

list = repo.Search(a => a.Title == "word").Filter(a => a.Views, 1, 1000).ToList();
list = repo.Search(a => a.Title == "word" && a.Tags.Contains("user1")).Filter(a => a.Views, 1, 1000).ToList();
list = repo.Search("word").ToList();
list = repo.Search("@title:word").ToList();
```
Expand Down
4 changes: 2 additions & 2 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ class TestDoc
public string Content { get; set; }

[FtTagField("tags")]
public string Tags { get; set; }
public string[] Tags { get; set; } //or string
[FtNumericField("views")]
public int Views { get; set; }
Expand All @@ -294,7 +294,7 @@ var list = repo.Search("*").InFields(a => new { a.Title }).ToList();
list = repo.Search("*").Return(a => new { a.Title, a.Tags }).ToList();
list = repo.Search("*").Return(a => new { tit1 = a.Title, tgs1 = a.Tags, a.Title, a.Tags }).ToList();

list = repo.Search(a => a.Title == "word").Filter(a => a.Views, 1, 1000).ToList();
list = repo.Search(a => a.Title == "word" && a.Tags.Contains("user1")).Filter(a => a.Views, 1, 1000).ToList();
list = repo.Search("word").ToList();
list = repo.Search("@title:word").ToList();
```
Expand Down
125 changes: 121 additions & 4 deletions src/FreeRedis/RedisClient/Modules/RediSearch/FtDocumentRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ public FtDocumentRepositorySearchBuilder<T> Search(string query = "*")
}

internal protected int ToTimestamp(DateTime dt) => (int)dt.Subtract(new DateTime(1970, 1, 1)).TotalSeconds;
internal protected List<KeyValuePair<string, string>> ParseSelectorExpression(Expression selector)
internal protected List<KeyValuePair<string, string>> ParseSelectorExpression(Expression selector, bool isQuoteFieldName = false)
{
var fieldValues = new List<KeyValuePair<string, string>>();
if (selector is LambdaExpression lambdaExp) selector = lambdaExp.Body;
Expand All @@ -205,7 +205,7 @@ internal protected List<KeyValuePair<string, string>> ParseSelectorExpression(Ex
for (var a = 0; a < newExp?.Members?.Count; a++)
{
var left = newExp.Members[a].Name;
var right = ParseQueryExpression(newExp.Arguments[a], new ParseQueryExpressionOptions { IsQuoteFieldName = false });
var right = ParseQueryExpression(newExp.Arguments[a], new ParseQueryExpressionOptions { IsQuoteFieldName = isQuoteFieldName });
fieldValues.Add(new KeyValuePair<string, string>(left, right));
}
}
Expand All @@ -217,7 +217,7 @@ internal protected List<KeyValuePair<string, string>> ParseSelectorExpression(Ex
var initAssignExp = (initExp.Bindings[a] as MemberAssignment);
if (initAssignExp == null) continue;
var left = initAssignExp.Member.Name;
var right = ParseQueryExpression(initAssignExp.Expression, new ParseQueryExpressionOptions { IsQuoteFieldName = false });
var right = ParseQueryExpression(initAssignExp.Expression, new ParseQueryExpressionOptions { IsQuoteFieldName = isQuoteFieldName });
fieldValues.Add(new KeyValuePair<string, string>(left, right));
}
}
Expand Down Expand Up @@ -309,6 +309,8 @@ string toFtTagString(string expResultStr)
if (string.IsNullOrEmpty(memberParseResult) == false) return memberParseResult;

if (memberExp.IsParameter() == false) return toFt(Expression.Lambda(exp).Compile().DynamicInvoke());
if (_schema.KeyProperty.Name == memberExp.Member.Name)
return options.IsQuoteFieldName ? $"@__key" : "__key";
if (_schema.FieldsMap.TryGetValue(memberExp.Member.Name, out var field))
return options.IsQuoteFieldName ? $"@{field.FieldAttribute.FieldName}" : field.FieldAttribute.FieldName;
break;
Expand Down Expand Up @@ -659,7 +661,10 @@ public List<T> ToList(out long total)
if (prop == null) continue;
if (kv.Value == null) continue;
if (kv.Value is string valstr && _repository._schema.FieldsMap.TryGetValue(prop.Name, out var field) && field.FieldType == FieldType.Tag)
ttype.SetPropertyOrFieldValue(item, prop.Name, valstr.Split(new[] { (field.FieldAttribute as FtTagFieldAttribute).Separator ?? "," }, StringSplitOptions.None));
ttype.SetPropertyOrFieldValue(item, prop.Name,
field.Property.PropertyType.IsArrayOrList() ?
field.Property.PropertyType.FromObject(valstr.Split(new[] { (field.FieldAttribute as FtTagFieldAttribute).Separator ?? "," }, StringSplitOptions.None)) : valstr
);
else
ttype.SetPropertyOrFieldValue(item, prop.Name, prop.GetPropertyOrFieldType().FromObject(kv.Value));
}
Expand Down Expand Up @@ -790,4 +795,116 @@ public FtDocumentRepositorySearchBuilder<T> Dialect(int value)
return this;
}
}


public class FtDocumentRepositoryAggregateBuilder<T>
{
AggregateBuilder _aggregateBuilder;
FtDocumentRepository<T> _repository;
internal FtDocumentRepositoryAggregateBuilder(FtDocumentRepository<T> repository, string index, string query)
{
_repository = repository;
_aggregateBuilder = new AggregateBuilder(_repository._client, index, query);
}

//public List<T> ToList() => ToList(out var _);
//public List<T> ToList(out long total)
//{
// var prefix = _repository._schema.DocumentAttribute.Prefix;
// var keyProperty = _repository._schema.KeyProperty;
// var result = _aggregateBuilder.Execute();
// total = result.Total;
// var ttype = typeof(T);
// return result.Documents.Select(doc =>
// {
// var item = (T)ttype.CreateInstanceGetDefaultValue();
// foreach (var kv in doc.Body)
// {
// var name = kv.Key.Replace("-", "_");
// var prop = ttype.GetPropertyOrFieldIgnoreCase(name);
// if (prop == null) continue;
// if (kv.Value == null) continue;
// if (kv.Value is string valstr && _repository._schema.FieldsMap.TryGetValue(prop.Name, out var field) && field.FieldType == FieldType.Tag)
// ttype.SetPropertyOrFieldValue(item, prop.Name, valstr.Split(new[] { (field.FieldAttribute as FtTagFieldAttribute).Separator ?? "," }, StringSplitOptions.None));
// else
// ttype.SetPropertyOrFieldValue(item, prop.Name, prop.GetPropertyOrFieldType().FromObject(kv.Value));
// }
// var itemId = doc.Id;
// if (!string.IsNullOrEmpty(prefix))
// if (itemId.StartsWith(prefix))
// itemId = itemId.Substring(prefix.Length);
// typeof(T).SetPropertyOrFieldValue(item, keyProperty.Name, keyProperty.PropertyType.FromObject(itemId));
// return item;
// }).ToList();
//}

public FtDocumentRepositoryAggregateBuilder<T> Verbatim(bool value = true)
{
_aggregateBuilder.Verbatim(value);
return this;
}
public FtDocumentRepositoryAggregateBuilder<T> Load(Expression<Func<T, object>> selector)
{
var fields = _repository.ParseSelectorExpression(selector.Body).Select(a => a.Value).ToArray();
if (fields.Any()) _aggregateBuilder.Load(fields);
return this;
}
public FtDocumentRepositoryAggregateBuilder<T> Timeout(long milliseconds)
{
_aggregateBuilder.Timeout(milliseconds);
return this;
}
public FtDocumentRepositoryAggregateBuilder<T> GroupBy(params string[] properties)
{
_aggregateBuilder.GroupBy(properties);
return this;
}
public FtDocumentRepositoryAggregateBuilder<T> GroupBy(string[] properties = null, params AggregateReduce[] reduces)
{
_aggregateBuilder.GroupBy(properties, reduces);
return this;
}
public FtDocumentRepositoryAggregateBuilder<T> SortBy(string property, bool desc = false)
{
_aggregateBuilder.SortBy(property, desc);
return this;
}
public FtDocumentRepositoryAggregateBuilder<T> SortBy(string[] properties, bool[] desc, int max = 0)
{
_aggregateBuilder.SortBy(properties, desc, max);
return this;
}
public FtDocumentRepositoryAggregateBuilder<T> Apply(Expression<Func<T, object>> selector)
{
var applies = _repository.ParseSelectorExpression(selector.Body, true);
foreach (var apply in applies)
_aggregateBuilder.Apply(apply.Value, apply.Key);
return this;
}
public FtDocumentRepositoryAggregateBuilder<T> Limit(long offset, long num)
{
_aggregateBuilder.Limit(offset, num);
return this;
}
public FtDocumentRepositoryAggregateBuilder<T> Filter(string value)
{
_aggregateBuilder.Filter(value);
return this;
}
public FtDocumentRepositoryAggregateBuilder<T> WithCursor(int count = -1, long maxIdle = -1)
{
_aggregateBuilder.WithCursor(count, maxIdle);
return this;
}
public FtDocumentRepositoryAggregateBuilder<T> Params(string name, string value)
{
_aggregateBuilder.Params(name, value);
return this;
}
public FtDocumentRepositoryAggregateBuilder<T> Dialect(int value)
{
_aggregateBuilder.Dialect(value);
return this;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,11 @@ public void FtDocumentRepository()
[Fact]
public void FtSearch()
{
var rt = cli.FtSearch("index_contacts", "(@email:*wjx\\.cn*) (@companyid==10096)")
.Limit(0, 10)
.Dialect(4)
.Execute();

var idxName = Guid.NewGuid().ToString();
cli.FtCreate(idxName)
.On(IndexDataType.Hash)
Expand Down Expand Up @@ -301,5 +306,99 @@ public void FtCreate()
.AddTagField("$.categories", alias: "categories")
.Execute();
}


[Fact]
public void TestContactsUserIndex()
{
var repo = cli.FtDocumentRepository<ContactsUserIndex>();
//FT.SEARCH index_contacts "(@email:*wjx\\.cn*) (@companyid==10096)" dialect 4
var rt = repo.Search(@"(@email:*wjx\.cn*) (@companyid==10096)").Dialect(4).ToList();

var rt2 = repo.Search(a => a.UEmail.Contains("wjx.cn") && a.CompanyId == 10096).Dialect(4).ToList();
}

[FtDocument("index_contacts", Prefix = "contactsuser:")]
public class ContactsUserIndex
{
/// <summary>
/// 用户唯一编号
/// </summary>

[FtKey]
public long Id { get; set; }

/// <summary>
/// 用户编号
/// </summary>
[FtTextField("userid")]
public string UserId { get; set; }
/// <summary>
/// 用户姓名
/// </summary>
[FtTextField("name")]
public string Name { get; set; }
/// <summary>
/// 用户所属部门
/// </summary>
[FtTagField("department")]
public string Department { get; set; }

/// <summary>
/// 企业编号
/// </summary>
[FtNumericField("companyid")]
public int CompanyId { get; set; }

/// <summary>
/// 用户自定义标签
/// </summary>
[FtTagField("utags")]
public string UTags { get; set; }
/// <summary>
/// 添加时间
/// </summary>
[FtNumericField("addtime", Sortable = true)]
public long AddTime { get; set; }
/// <summary>
/// 更新时间
/// </summary>
[FtNumericField("updatetime")]
public long UpdateTime { get; set; }

/// <summary>
/// 手机号
/// </summary>
[FtTextField("umobile")]
public string UMobile { get; set; }
/// <summary>
/// 邮箱
/// </summary>
[FtTextField("uemail")]
public string UEmail { get; set; }
/// <summary>
/// 昵称
/// </summary>
[FtTextField("unickname")]
public string UNickname { get; set; }
/// <summary>
/// 生日
/// </summary>
[FtNumericField("ubirthday")]
public long UBirthday { get; set; }

[FtNumericField("lastmsgtime")]
public long LastMsgTime { get; set; }

[FtNumericField("lastjointime")]
public long LastJoinTime { get; set; }

/// <summary>
/// 用户信息标识位
/// </summary>
[FtNumericField("uinfomap")]
public long UInfoMap { get; set; }
}
}

}

0 comments on commit ea0b305

Please sign in to comment.