ElasticSearch: used file-scoped namespaces
This commit is contained in:
parent
cd879ed2a7
commit
53237d8c6f
@ -23,25 +23,24 @@
|
||||
*
|
||||
*/
|
||||
|
||||
namespace ASC.ElasticSearch
|
||||
{
|
||||
public enum Analyzer
|
||||
{
|
||||
standard,
|
||||
whitespace,
|
||||
uax_url_email
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum CharFilter
|
||||
{
|
||||
io,
|
||||
html
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum Filter
|
||||
{
|
||||
lowercase
|
||||
}
|
||||
namespace ASC.ElasticSearch;
|
||||
|
||||
public enum Analyzer
|
||||
{
|
||||
standard,
|
||||
whitespace,
|
||||
uax_url_email
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum CharFilter
|
||||
{
|
||||
io,
|
||||
html
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum Filter
|
||||
{
|
||||
lowercase
|
||||
}
|
||||
|
@ -23,11 +23,10 @@
|
||||
*
|
||||
*/
|
||||
|
||||
namespace ASC.ElasticSearch
|
||||
namespace ASC.ElasticSearch;
|
||||
|
||||
public class Document
|
||||
{
|
||||
public class Document
|
||||
{
|
||||
public string Data { get; set; }
|
||||
public Attachment Attachment { get; set; }
|
||||
}
|
||||
public string Data { get; set; }
|
||||
public Attachment Attachment { get; set; }
|
||||
}
|
||||
|
@ -1,16 +1,15 @@
|
||||
namespace ASC.ElasticSearch
|
||||
namespace ASC.ElasticSearch;
|
||||
|
||||
public interface ISearchItem
|
||||
{
|
||||
public interface ISearchItem
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public int TenantId { get; set; }
|
||||
public string IndexName { get; }
|
||||
public int Id { get; set; }
|
||||
public int TenantId { get; set; }
|
||||
public string IndexName { get; }
|
||||
|
||||
public Expression<Func<ISearchItem, object[]>> GetSearchContentFields(SearchSettingsHelper searchSettings);
|
||||
}
|
||||
|
||||
public interface ISearchItemDocument : ISearchItem
|
||||
{
|
||||
public Document Document { get; set; }
|
||||
}
|
||||
public Expression<Func<ISearchItem, object[]>> GetSearchContentFields(SearchSettingsHelper searchSettings);
|
||||
}
|
||||
|
||||
public interface ISearchItemDocument : ISearchItem
|
||||
{
|
||||
public Document Document { get; set; }
|
||||
}
|
||||
|
@ -23,170 +23,169 @@
|
||||
*
|
||||
*/
|
||||
|
||||
namespace ASC.ElasticSearch.Core
|
||||
{
|
||||
[Serializable]
|
||||
public class SearchSettings : ISettings
|
||||
{
|
||||
public string Data { get; set; }
|
||||
public Guid ID => new Guid("{93784AB2-10B5-4C2F-9B36-F2662CCCF316}");
|
||||
internal List<SearchSettingsItem> Items
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_items != null)
|
||||
{
|
||||
return _items;
|
||||
}
|
||||
namespace ASC.ElasticSearch.Core;
|
||||
|
||||
var parsed = JsonConvert.DeserializeObject<List<SearchSettingsItem>>(Data ?? "");
|
||||
|
||||
return _items = parsed ?? new List<SearchSettingsItem>();
|
||||
}
|
||||
set
|
||||
{
|
||||
_items = value;
|
||||
}
|
||||
}
|
||||
|
||||
private List<SearchSettingsItem> _items;
|
||||
|
||||
public ISettings GetDefault(IServiceProvider serviceProvider)
|
||||
{
|
||||
return new SearchSettings();
|
||||
}
|
||||
|
||||
internal bool IsEnabled(string name)
|
||||
{
|
||||
var wrapper = Items.FirstOrDefault(r => r.ID == name);
|
||||
|
||||
return wrapper != null && wrapper.Enabled;
|
||||
}
|
||||
}
|
||||
|
||||
[Scope]
|
||||
public class SearchSettingsHelper
|
||||
[Serializable]
|
||||
public class SearchSettings : ISettings
|
||||
{
|
||||
public string Data { get; set; }
|
||||
public Guid ID => new Guid("{93784AB2-10B5-4C2F-9B36-F2662CCCF316}");
|
||||
internal List<SearchSettingsItem> Items
|
||||
{
|
||||
public IConfiguration Configuration { get; }
|
||||
internal List<IFactoryIndexer> AllItems =>
|
||||
_allItems ??= _serviceProvider.GetService<IEnumerable<IFactoryIndexer>>().ToList();
|
||||
|
||||
private readonly TenantManager _tenantManager;
|
||||
private readonly SettingsManager _settingsManager;
|
||||
private readonly CoreBaseSettings _coreBaseSettings;
|
||||
private readonly ICacheNotify<ReIndexAction> _cacheNotify;
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private List<IFactoryIndexer> _allItems;
|
||||
|
||||
public SearchSettingsHelper(
|
||||
TenantManager tenantManager,
|
||||
SettingsManager settingsManager,
|
||||
CoreBaseSettings coreBaseSettings,
|
||||
ICacheNotify<ReIndexAction> cacheNotify,
|
||||
IServiceProvider serviceProvider,
|
||||
IConfiguration configuration)
|
||||
get
|
||||
{
|
||||
_tenantManager = tenantManager;
|
||||
_settingsManager = settingsManager;
|
||||
_coreBaseSettings = coreBaseSettings;
|
||||
_cacheNotify = cacheNotify;
|
||||
_serviceProvider = serviceProvider;
|
||||
Configuration = configuration;
|
||||
}
|
||||
|
||||
public List<SearchSettingsItem> GetAllItems()
|
||||
{
|
||||
if (!_coreBaseSettings.Standalone)
|
||||
if (_items != null)
|
||||
{
|
||||
return new List<SearchSettingsItem>();
|
||||
return _items;
|
||||
}
|
||||
|
||||
var settings = _settingsManager.Load<SearchSettings>();
|
||||
|
||||
return AllItems.Select(r => new SearchSettingsItem
|
||||
{
|
||||
ID = r.IndexName,
|
||||
Enabled = settings.IsEnabled(r.IndexName),
|
||||
Title = r.SettingsTitle
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
public void Set(List<SearchSettingsItem> items)
|
||||
{
|
||||
if (!_coreBaseSettings.Standalone)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var parsed = JsonConvert.DeserializeObject<List<SearchSettingsItem>>(Data ?? "");
|
||||
|
||||
var settings = _settingsManager.Load<SearchSettings>();
|
||||
|
||||
var settingsItems = settings.Items;
|
||||
var toReIndex = !settingsItems.Any() ? items.Where(r => r.Enabled).ToList() : items.Where(item => settingsItems.Any(r => r.ID == item.ID && r.Enabled != item.Enabled)).ToList();
|
||||
|
||||
settings.Items = items;
|
||||
settings.Data = JsonConvert.SerializeObject(items);
|
||||
_settingsManager.Save(settings);
|
||||
return _items = parsed ?? new List<SearchSettingsItem>();
|
||||
}
|
||||
set
|
||||
{
|
||||
_items = value;
|
||||
}
|
||||
}
|
||||
|
||||
var action = new ReIndexAction() { Tenant = _tenantManager.GetCurrentTenant().TenantId };
|
||||
action.Names.AddRange(toReIndex.Select(r => r.ID).ToList());
|
||||
private List<SearchSettingsItem> _items;
|
||||
|
||||
_cacheNotify.Publish(action, CacheNotifyAction.Any);
|
||||
public ISettings GetDefault(IServiceProvider serviceProvider)
|
||||
{
|
||||
return new SearchSettings();
|
||||
}
|
||||
|
||||
internal bool IsEnabled(string name)
|
||||
{
|
||||
var wrapper = Items.FirstOrDefault(r => r.ID == name);
|
||||
|
||||
return wrapper != null && wrapper.Enabled;
|
||||
}
|
||||
}
|
||||
|
||||
[Scope]
|
||||
public class SearchSettingsHelper
|
||||
{
|
||||
public IConfiguration Configuration { get; }
|
||||
internal List<IFactoryIndexer> AllItems =>
|
||||
_allItems ??= _serviceProvider.GetService<IEnumerable<IFactoryIndexer>>().ToList();
|
||||
|
||||
private readonly TenantManager _tenantManager;
|
||||
private readonly SettingsManager _settingsManager;
|
||||
private readonly CoreBaseSettings _coreBaseSettings;
|
||||
private readonly ICacheNotify<ReIndexAction> _cacheNotify;
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private List<IFactoryIndexer> _allItems;
|
||||
|
||||
public SearchSettingsHelper(
|
||||
TenantManager tenantManager,
|
||||
SettingsManager settingsManager,
|
||||
CoreBaseSettings coreBaseSettings,
|
||||
ICacheNotify<ReIndexAction> cacheNotify,
|
||||
IServiceProvider serviceProvider,
|
||||
IConfiguration configuration)
|
||||
{
|
||||
_tenantManager = tenantManager;
|
||||
_settingsManager = settingsManager;
|
||||
_coreBaseSettings = coreBaseSettings;
|
||||
_cacheNotify = cacheNotify;
|
||||
_serviceProvider = serviceProvider;
|
||||
Configuration = configuration;
|
||||
}
|
||||
|
||||
public List<SearchSettingsItem> GetAllItems()
|
||||
{
|
||||
if (!_coreBaseSettings.Standalone)
|
||||
{
|
||||
return new List<SearchSettingsItem>();
|
||||
}
|
||||
|
||||
public bool CanIndexByContent<T>(int tenantId) where T : class, ISearchItem
|
||||
var settings = _settingsManager.Load<SearchSettings>();
|
||||
|
||||
return AllItems.Select(r => new SearchSettingsItem
|
||||
{
|
||||
return CanIndexByContent(typeof(T), tenantId);
|
||||
ID = r.IndexName,
|
||||
Enabled = settings.IsEnabled(r.IndexName),
|
||||
Title = r.SettingsTitle
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
public void Set(List<SearchSettingsItem> items)
|
||||
{
|
||||
if (!_coreBaseSettings.Standalone)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
public bool CanIndexByContent(Type t, int tenantId)
|
||||
var settings = _settingsManager.Load<SearchSettings>();
|
||||
|
||||
var settingsItems = settings.Items;
|
||||
var toReIndex = !settingsItems.Any() ? items.Where(r => r.Enabled).ToList() : items.Where(item => settingsItems.Any(r => r.ID == item.ID && r.Enabled != item.Enabled)).ToList();
|
||||
|
||||
settings.Items = items;
|
||||
settings.Data = JsonConvert.SerializeObject(items);
|
||||
_settingsManager.Save(settings);
|
||||
|
||||
var action = new ReIndexAction() { Tenant = _tenantManager.GetCurrentTenant().TenantId };
|
||||
action.Names.AddRange(toReIndex.Select(r => r.ID).ToList());
|
||||
|
||||
_cacheNotify.Publish(action, CacheNotifyAction.Any);
|
||||
}
|
||||
|
||||
public bool CanIndexByContent<T>(int tenantId) where T : class, ISearchItem
|
||||
{
|
||||
return CanIndexByContent(typeof(T), tenantId);
|
||||
}
|
||||
|
||||
public bool CanIndexByContent(Type t, int tenantId)
|
||||
{
|
||||
if (!typeof(ISearchItemDocument).IsAssignableFrom(t))
|
||||
{
|
||||
if (!typeof(ISearchItemDocument).IsAssignableFrom(t))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Convert.ToBoolean(Configuration["core:search-by-content"] ?? "false"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!_coreBaseSettings.Standalone)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
var settings = _settingsManager.LoadForTenant<SearchSettings>(tenantId);
|
||||
|
||||
return settings.IsEnabled(((ISearchItemDocument)_serviceProvider.GetService(t)).IndexName);
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool CanSearchByContent<T>() where T : class, ISearchItem
|
||||
if (Convert.ToBoolean(Configuration["core:search-by-content"] ?? "false"))
|
||||
{
|
||||
return CanSearchByContent(typeof(T));
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool CanSearchByContent(Type t)
|
||||
if (!_coreBaseSettings.Standalone)
|
||||
{
|
||||
var tenantId = _tenantManager.GetCurrentTenant().TenantId;
|
||||
if (!CanIndexByContent(t, tenantId))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_coreBaseSettings.Standalone)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
var settings = _settingsManager.LoadForTenant<SearchSettings>(tenantId);
|
||||
|
||||
return _tenantManager.GetTenantQuota(tenantId).ContentSearch;
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class SearchSettingsItem
|
||||
{
|
||||
public string ID { get; set; }
|
||||
public bool Enabled { get; set; }
|
||||
public string Title { get; set; }
|
||||
}
|
||||
return settings.IsEnabled(((ISearchItemDocument)_serviceProvider.GetService(t)).IndexName);
|
||||
}
|
||||
|
||||
public bool CanSearchByContent<T>() where T : class, ISearchItem
|
||||
{
|
||||
return CanSearchByContent(typeof(T));
|
||||
}
|
||||
|
||||
public bool CanSearchByContent(Type t)
|
||||
{
|
||||
var tenantId = _tenantManager.GetCurrentTenant().TenantId;
|
||||
if (!CanIndexByContent(t, tenantId))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_coreBaseSettings.Standalone)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return _tenantManager.GetTenantQuota(tenantId).ContentSearch;
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class SearchSettingsItem
|
||||
{
|
||||
public string ID { get; set; }
|
||||
public bool Enabled { get; set; }
|
||||
public string Title { get; set; }
|
||||
}
|
||||
|
@ -23,447 +23,446 @@
|
||||
*
|
||||
*/
|
||||
|
||||
namespace ASC.ElasticSearch
|
||||
namespace ASC.ElasticSearch;
|
||||
|
||||
[Scope]
|
||||
public class Selector<T> where T : class, ISearchItem
|
||||
{
|
||||
[Scope]
|
||||
public class Selector<T> where T : class, ISearchItem
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private readonly QueryContainerDescriptor<T> _queryContainerDescriptor = new QueryContainerDescriptor<T>();
|
||||
private SortDescriptor<T> _sortContainerDescriptor = new SortDescriptor<T>();
|
||||
private QueryContainer _queryContainer = new QueryContainer();
|
||||
private int _limit = 1000, offset;
|
||||
|
||||
public Selector(IServiceProvider serviceProvider)
|
||||
{
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private readonly QueryContainerDescriptor<T> _queryContainerDescriptor = new QueryContainerDescriptor<T>();
|
||||
private SortDescriptor<T> _sortContainerDescriptor = new SortDescriptor<T>();
|
||||
private QueryContainer _queryContainer = new QueryContainer();
|
||||
private int _limit = 1000, offset;
|
||||
_serviceProvider = serviceProvider;
|
||||
}
|
||||
|
||||
public Selector(IServiceProvider serviceProvider)
|
||||
public Selector<T> Where<TProperty>(Expression<Func<T, TProperty>> selector, TProperty value)
|
||||
{
|
||||
_queryContainer = _queryContainer && +Wrap(selector, (w, r) => r.Term(w, value));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public Selector<T> Where(Expression<Func<T, Guid>> selector, Guid value)
|
||||
{
|
||||
_queryContainer = _queryContainer && +Wrap(selector, (a, w) => w.Match(r => r.Field(a).Query(value.ToString())));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public Selector<T> Gt(Expression<Func<T, object>> selector, double? value)
|
||||
{
|
||||
_queryContainer = _queryContainer && +Wrap(selector, (w, r) => r.Range(a => a.Field(w).GreaterThan(value)));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public Selector<T> Lt(Expression<Func<T, object>> selector, double? value)
|
||||
{
|
||||
_queryContainer = _queryContainer && +Wrap(selector, (w, r) => r.Range(a => a.Field(w).LessThan(value)));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public Selector<T> Gt(Expression<Func<T, object>> selector, DateTime? value)
|
||||
{
|
||||
_queryContainer = _queryContainer && +Wrap(selector, (w, r) => r.DateRange(a => a.Field(w).GreaterThan(value)));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public Selector<T> Ge(Expression<Func<T, object>> selector, DateTime? value)
|
||||
{
|
||||
_queryContainer = _queryContainer && +Wrap(selector, (w, r) => r.DateRange(a => a.Field(w).GreaterThanOrEquals(value)));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public Selector<T> Lt(Expression<Func<T, object>> selector, DateTime? value)
|
||||
{
|
||||
_queryContainer = _queryContainer && +Wrap(selector, (w, r) => r.DateRange(a => a.Field(w).LessThan(value)));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public Selector<T> Le(Expression<Func<T, object>> selector, DateTime? value)
|
||||
{
|
||||
_queryContainer = _queryContainer && +Wrap(selector, (w, r) => r.DateRange(a => a.Field(w).LessThanOrEquals(value)));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public Selector<T> In<TValue>(Expression<Func<T, object>> selector, TValue[] values)
|
||||
{
|
||||
_queryContainer = _queryContainer && +Wrap(selector, (w, r) => r.Terms(a => a.Field(w).Terms(values)));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public Selector<T> InAll<TValue>(Expression<Func<T, object>> selector, TValue[] values)
|
||||
{
|
||||
foreach (var v in values)
|
||||
{
|
||||
_serviceProvider = serviceProvider;
|
||||
}
|
||||
|
||||
public Selector<T> Where<TProperty>(Expression<Func<T, TProperty>> selector, TProperty value)
|
||||
{
|
||||
_queryContainer = _queryContainer && +Wrap(selector, (w, r) => r.Term(w, value));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public Selector<T> Where(Expression<Func<T, Guid>> selector, Guid value)
|
||||
{
|
||||
_queryContainer = _queryContainer && +Wrap(selector, (a, w) => w.Match(r => r.Field(a).Query(value.ToString())));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public Selector<T> Gt(Expression<Func<T, object>> selector, double? value)
|
||||
{
|
||||
_queryContainer = _queryContainer && +Wrap(selector, (w, r) => r.Range(a => a.Field(w).GreaterThan(value)));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public Selector<T> Lt(Expression<Func<T, object>> selector, double? value)
|
||||
{
|
||||
_queryContainer = _queryContainer && +Wrap(selector, (w, r) => r.Range(a => a.Field(w).LessThan(value)));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public Selector<T> Gt(Expression<Func<T, object>> selector, DateTime? value)
|
||||
{
|
||||
_queryContainer = _queryContainer && +Wrap(selector, (w, r) => r.DateRange(a => a.Field(w).GreaterThan(value)));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public Selector<T> Ge(Expression<Func<T, object>> selector, DateTime? value)
|
||||
{
|
||||
_queryContainer = _queryContainer && +Wrap(selector, (w, r) => r.DateRange(a => a.Field(w).GreaterThanOrEquals(value)));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public Selector<T> Lt(Expression<Func<T, object>> selector, DateTime? value)
|
||||
{
|
||||
_queryContainer = _queryContainer && +Wrap(selector, (w, r) => r.DateRange(a => a.Field(w).LessThan(value)));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public Selector<T> Le(Expression<Func<T, object>> selector, DateTime? value)
|
||||
{
|
||||
_queryContainer = _queryContainer && +Wrap(selector, (w, r) => r.DateRange(a => a.Field(w).LessThanOrEquals(value)));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public Selector<T> In<TValue>(Expression<Func<T, object>> selector, TValue[] values)
|
||||
{
|
||||
_queryContainer = _queryContainer && +Wrap(selector, (w, r) => r.Terms(a => a.Field(w).Terms(values)));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public Selector<T> InAll<TValue>(Expression<Func<T, object>> selector, TValue[] values)
|
||||
{
|
||||
foreach (var v in values)
|
||||
{
|
||||
var v1 = v;
|
||||
_queryContainer = _queryContainer && +Wrap(selector, (w, r) => r.Term(a => a.Field(w).Value(v1)));
|
||||
}
|
||||
|
||||
return this;
|
||||
var v1 = v;
|
||||
_queryContainer = _queryContainer && +Wrap(selector, (w, r) => r.Term(a => a.Field(w).Value(v1)));
|
||||
}
|
||||
|
||||
public Selector<T> Match(Expression<Func<T, object>> selector, string value)
|
||||
{
|
||||
value = value.PrepareToSearch();
|
||||
return this;
|
||||
}
|
||||
|
||||
if (IsExactlyPhrase(value))
|
||||
public Selector<T> Match(Expression<Func<T, object>> selector, string value)
|
||||
{
|
||||
value = value.PrepareToSearch();
|
||||
|
||||
if (IsExactlyPhrase(value))
|
||||
{
|
||||
_queryContainer &= Wrap(selector, (a, w) => w.MatchPhrase(r => r.Field(a).Query(value.TrimQuotes())));
|
||||
}
|
||||
else if (value.HasOtherLetter() || IsExactly(value))
|
||||
{
|
||||
_queryContainer &= Wrap(selector, (a, w) => w.Match(r => r.Field(a).Query(value.TrimQuotes())));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IsPhrase(value))
|
||||
{
|
||||
_queryContainer &= Wrap(selector, (a, w) => w.MatchPhrase(r => r.Field(a).Query(value.TrimQuotes())));
|
||||
}
|
||||
else if (value.HasOtherLetter() || IsExactly(value))
|
||||
{
|
||||
_queryContainer &= Wrap(selector, (a, w) => w.Match(r => r.Field(a).Query(value.TrimQuotes())));
|
||||
var phrase = value.Split(' ');
|
||||
foreach (var p in phrase)
|
||||
{
|
||||
var p1 = p;
|
||||
_queryContainer &= Wrap(selector, (a, w) => w.Wildcard(r => r.Field(a).Value(p1.WrapAsterisk())));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IsPhrase(value))
|
||||
{
|
||||
var phrase = value.Split(' ');
|
||||
foreach (var p in phrase)
|
||||
{
|
||||
var p1 = p;
|
||||
_queryContainer &= Wrap(selector, (a, w) => w.Wildcard(r => r.Field(a).Value(p1.WrapAsterisk())));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_queryContainer &= Wrap(selector, (a, w) => w.Wildcard(r => r.Field(a).Value(value.WrapAsterisk())));
|
||||
}
|
||||
|
||||
_queryContainer &= Wrap(selector, (a, w) => w.Wildcard(r => r.Field(a).Value(value.WrapAsterisk())));
|
||||
}
|
||||
|
||||
if (IsExactly(value))
|
||||
{
|
||||
_queryContainer |= Wrap(selector, (a, w) => w.MatchPhrase(r => r.Field(a).Query(value)));
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public Selector<T> Match(Expression<Func<T, object[]>> selector, string value)
|
||||
if (IsExactly(value))
|
||||
{
|
||||
Match(() => ((NewArrayExpression)selector.Body).Expressions.ToArray(), value);
|
||||
|
||||
return this;
|
||||
_queryContainer |= Wrap(selector, (a, w) => w.MatchPhrase(r => r.Field(a).Query(value)));
|
||||
}
|
||||
|
||||
public Selector<T> MatchAll(string value)
|
||||
{
|
||||
Match(() =>
|
||||
{
|
||||
var t = _serviceProvider.GetService<T>();
|
||||
var searchSettingsHelper = _serviceProvider.GetService<SearchSettingsHelper>();
|
||||
return this;
|
||||
}
|
||||
|
||||
return ((NewArrayExpression)(t.GetSearchContentFields(searchSettingsHelper)).Body).Expressions.ToArray();
|
||||
},
|
||||
value);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public Selector<T> Sort(Expression<Func<T, object>> selector, bool asc)
|
||||
{
|
||||
_sortContainerDescriptor = _sortContainerDescriptor.Field(selector, asc ? SortOrder.Ascending : SortOrder.Descending);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public Selector<T> Limit(int newOffset = 0, int newLimit = 1000)
|
||||
{
|
||||
offset = newOffset;
|
||||
_limit = newLimit;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public Selector<T> Or(Expression<Func<Selector<T>, Selector<T>>> selectorLeft, Expression<Func<Selector<T>, Selector<T>>> selectorRight)
|
||||
{
|
||||
return new Selector<T>(_serviceProvider)
|
||||
{
|
||||
_queryContainer = _queryContainer &
|
||||
(selectorLeft.Compile()(new Selector<T>(_serviceProvider))._queryContainer |
|
||||
selectorRight.Compile()(new Selector<T>(_serviceProvider))._queryContainer)
|
||||
};
|
||||
}
|
||||
|
||||
public static Selector<T> Or(Selector<T> selectorLeft, Selector<T> selectorRight)
|
||||
{
|
||||
return new Selector<T>(selectorLeft._serviceProvider)
|
||||
{
|
||||
_queryContainer = selectorLeft._queryContainer | selectorRight._queryContainer
|
||||
};
|
||||
}
|
||||
|
||||
public Selector<T> Not(Expression<Func<Selector<T>, Selector<T>>> selector)
|
||||
{
|
||||
return new Selector<T>(_serviceProvider)
|
||||
{
|
||||
_queryContainer = _queryContainer & !selector.Compile()(new Selector<T>(_serviceProvider))._queryContainer
|
||||
};
|
||||
}
|
||||
|
||||
public static Selector<T> Not(Selector<T> selector)
|
||||
{
|
||||
return new Selector<T>(selector._serviceProvider)
|
||||
{
|
||||
_queryContainer = !selector._queryContainer
|
||||
};
|
||||
}
|
||||
|
||||
public static Selector<T> operator &(Selector<T> selectorLeft, Selector<T> selectorRight)
|
||||
{
|
||||
return new Selector<T>(selectorLeft._serviceProvider)
|
||||
{
|
||||
_queryContainer = selectorLeft._queryContainer & selectorRight._queryContainer
|
||||
};
|
||||
}
|
||||
|
||||
public static Selector<T> operator |(Selector<T> selectorLeft, Selector<T> selectorRight)
|
||||
{
|
||||
return Or(selectorLeft, selectorRight);
|
||||
}
|
||||
|
||||
public static Selector<T> operator !(Selector<T> selector)
|
||||
{
|
||||
return Not(selector);
|
||||
}
|
||||
|
||||
internal Func<SearchDescriptor<T>, ISearchRequest> GetDescriptor(BaseIndexer<T> indexer, bool onlyId = false)
|
||||
{
|
||||
return s =>
|
||||
{
|
||||
var result = s
|
||||
.Query(q => _queryContainer)
|
||||
.Index(indexer.IndexName)
|
||||
.Sort(r => _sortContainerDescriptor)
|
||||
.From(offset)
|
||||
.Size(_limit);
|
||||
|
||||
if (onlyId)
|
||||
{
|
||||
result = result.Source(r => r.Includes(a => a.Field("id")));
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
}
|
||||
|
||||
internal Func<DeleteByQueryDescriptor<T>, IDeleteByQueryRequest> GetDescriptorForDelete(BaseIndexer<T> indexer, bool immediately = true)
|
||||
{
|
||||
return s =>
|
||||
{
|
||||
var result = s
|
||||
.Query(q => _queryContainer)
|
||||
.Index(indexer.IndexName);
|
||||
if (immediately)
|
||||
{
|
||||
result.Refresh();
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
}
|
||||
|
||||
internal Func<UpdateByQueryDescriptor<T>, IUpdateByQueryRequest> GetDescriptorForUpdate(BaseIndexer<T> indexer, Func<ScriptDescriptor, IScript> script, bool immediately = true)
|
||||
{
|
||||
return s =>
|
||||
{
|
||||
var result = s
|
||||
.Query(q => _queryContainer)
|
||||
.Index(indexer.IndexName)
|
||||
.Script(script);
|
||||
|
||||
if (immediately)
|
||||
{
|
||||
result.Refresh();
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
}
|
||||
|
||||
private void Match(Func<Fields> propsFunc, string value)
|
||||
{
|
||||
if (string.IsNullOrEmpty(value))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
value = value.PrepareToSearch();
|
||||
|
||||
var props = propsFunc();
|
||||
|
||||
if (IsExactlyPhrase(value))
|
||||
{
|
||||
_queryContainer = _queryContainer && MultiPhrase(props, value.TrimQuotes());
|
||||
}
|
||||
else if (value.HasOtherLetter() || IsExactly(value))
|
||||
{
|
||||
_queryContainer = _queryContainer && MultiMatch(props, value.TrimQuotes());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IsPhrase(value))
|
||||
{
|
||||
var phrase = value.Split(' ');
|
||||
foreach (var p in phrase)
|
||||
{
|
||||
_queryContainer = _queryContainer && MultiWildCard(props, p.WrapAsterisk());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_queryContainer = _queryContainer && MultiWildCard(props, value.WrapAsterisk());
|
||||
}
|
||||
}
|
||||
|
||||
if (IsExactly(value))
|
||||
{
|
||||
_queryContainer = _queryContainer || MultiPhrase(props, value);
|
||||
}
|
||||
}
|
||||
|
||||
private QueryContainer Wrap(Field fieldSelector, Func<Field, QueryContainerDescriptor<T>, QueryContainer> selector)
|
||||
{
|
||||
var path = IsNested(fieldSelector);
|
||||
|
||||
if (string.IsNullOrEmpty(path) &&
|
||||
!string.IsNullOrEmpty(fieldSelector.Name) &&
|
||||
fieldSelector.Name.IndexOf(".", StringComparison.InvariantCulture) > 0)
|
||||
{
|
||||
var splitted = fieldSelector.Name.Split(':')[1];
|
||||
path = splitted.Split('.')[0];
|
||||
fieldSelector = new Field(splitted);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(path))
|
||||
{
|
||||
return _queryContainerDescriptor.Nested(a => a.Query(b => selector(fieldSelector, b)).Path(path));
|
||||
}
|
||||
|
||||
return selector(fieldSelector, _queryContainerDescriptor);
|
||||
}
|
||||
|
||||
private string IsNested(Field selector)
|
||||
{
|
||||
if (!(selector.Expression is LambdaExpression lambdaExpression))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (lambdaExpression.Body is MethodCallExpression methodCallExpression && methodCallExpression.Arguments.Count > 1)
|
||||
{
|
||||
return !(methodCallExpression.Arguments[0] is MemberExpression pathMember)
|
||||
? null
|
||||
: pathMember.Member.Name.ToLowerCamelCase();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private bool IsPhrase(string searchText)
|
||||
{
|
||||
return searchText.Contains(" ") || searchText.Contains("\r\n") || searchText.Contains("\n");
|
||||
}
|
||||
|
||||
private bool IsExactlyPhrase(string searchText)
|
||||
{
|
||||
return IsPhrase(searchText) && IsExactly(searchText);
|
||||
}
|
||||
|
||||
private bool IsExactly(string searchText)
|
||||
{
|
||||
return searchText.StartsWith("\"") && searchText.EndsWith("\"");
|
||||
}
|
||||
|
||||
private QueryContainer MultiMatch(Fields fields, string value)
|
||||
{
|
||||
var qcWildCard = new QueryContainer();
|
||||
|
||||
foreach (var field in fields)
|
||||
{
|
||||
var field1 = field;
|
||||
qcWildCard = qcWildCard || Wrap(field1, (a, w) => w.Match(r => r.Field(a).Query(value.ToLower())));
|
||||
}
|
||||
|
||||
return qcWildCard;
|
||||
}
|
||||
|
||||
private QueryContainer MultiWildCard(Fields fields, string value)
|
||||
{
|
||||
var qcWildCard = new QueryContainer();
|
||||
|
||||
foreach (var field in fields)
|
||||
{
|
||||
qcWildCard = qcWildCard || Wrap(field, (a, w) => w.Wildcard(r => r.Field(a).Value(value)));
|
||||
}
|
||||
|
||||
return qcWildCard;
|
||||
}
|
||||
|
||||
private QueryContainer MultiPhrase(Fields fields, string value)
|
||||
{
|
||||
var qcWildCard = new QueryContainer();
|
||||
|
||||
foreach (var field in fields)
|
||||
{
|
||||
qcWildCard = qcWildCard || Wrap(field, (a, w) => w.MatchPhrase(r => r.Field(a).Query(value.ToLower())));
|
||||
}
|
||||
|
||||
return qcWildCard;
|
||||
}
|
||||
}
|
||||
|
||||
internal static class StringExtension
|
||||
public Selector<T> Match(Expression<Func<T, object[]>> selector, string value)
|
||||
{
|
||||
private static bool Any(this string value, UnicodeCategory category)
|
||||
{
|
||||
return !string.IsNullOrWhiteSpace(value)
|
||||
&& value.Any(@char => char.GetUnicodeCategory(@char) == category);
|
||||
}
|
||||
Match(() => ((NewArrayExpression)selector.Body).Expressions.ToArray(), value);
|
||||
|
||||
public static bool HasOtherLetter(this string value)
|
||||
{
|
||||
return value.Any(UnicodeCategory.OtherLetter);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public static string WrapAsterisk(this string value)
|
||||
public Selector<T> MatchAll(string value)
|
||||
{
|
||||
Match(() =>
|
||||
{
|
||||
var result = value;
|
||||
var t = _serviceProvider.GetService<T>();
|
||||
var searchSettingsHelper = _serviceProvider.GetService<SearchSettingsHelper>();
|
||||
|
||||
if (!value.Contains("*") && !value.Contains("?"))
|
||||
return ((NewArrayExpression)(t.GetSearchContentFields(searchSettingsHelper)).Body).Expressions.ToArray();
|
||||
},
|
||||
value);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public Selector<T> Sort(Expression<Func<T, object>> selector, bool asc)
|
||||
{
|
||||
_sortContainerDescriptor = _sortContainerDescriptor.Field(selector, asc ? SortOrder.Ascending : SortOrder.Descending);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public Selector<T> Limit(int newOffset = 0, int newLimit = 1000)
|
||||
{
|
||||
offset = newOffset;
|
||||
_limit = newLimit;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public Selector<T> Or(Expression<Func<Selector<T>, Selector<T>>> selectorLeft, Expression<Func<Selector<T>, Selector<T>>> selectorRight)
|
||||
{
|
||||
return new Selector<T>(_serviceProvider)
|
||||
{
|
||||
_queryContainer = _queryContainer &
|
||||
(selectorLeft.Compile()(new Selector<T>(_serviceProvider))._queryContainer |
|
||||
selectorRight.Compile()(new Selector<T>(_serviceProvider))._queryContainer)
|
||||
};
|
||||
}
|
||||
|
||||
public static Selector<T> Or(Selector<T> selectorLeft, Selector<T> selectorRight)
|
||||
{
|
||||
return new Selector<T>(selectorLeft._serviceProvider)
|
||||
{
|
||||
_queryContainer = selectorLeft._queryContainer | selectorRight._queryContainer
|
||||
};
|
||||
}
|
||||
|
||||
public Selector<T> Not(Expression<Func<Selector<T>, Selector<T>>> selector)
|
||||
{
|
||||
return new Selector<T>(_serviceProvider)
|
||||
{
|
||||
_queryContainer = _queryContainer & !selector.Compile()(new Selector<T>(_serviceProvider))._queryContainer
|
||||
};
|
||||
}
|
||||
|
||||
public static Selector<T> Not(Selector<T> selector)
|
||||
{
|
||||
return new Selector<T>(selector._serviceProvider)
|
||||
{
|
||||
_queryContainer = !selector._queryContainer
|
||||
};
|
||||
}
|
||||
|
||||
public static Selector<T> operator &(Selector<T> selectorLeft, Selector<T> selectorRight)
|
||||
{
|
||||
return new Selector<T>(selectorLeft._serviceProvider)
|
||||
{
|
||||
_queryContainer = selectorLeft._queryContainer & selectorRight._queryContainer
|
||||
};
|
||||
}
|
||||
|
||||
public static Selector<T> operator |(Selector<T> selectorLeft, Selector<T> selectorRight)
|
||||
{
|
||||
return Or(selectorLeft, selectorRight);
|
||||
}
|
||||
|
||||
public static Selector<T> operator !(Selector<T> selector)
|
||||
{
|
||||
return Not(selector);
|
||||
}
|
||||
|
||||
internal Func<SearchDescriptor<T>, ISearchRequest> GetDescriptor(BaseIndexer<T> indexer, bool onlyId = false)
|
||||
{
|
||||
return s =>
|
||||
{
|
||||
var result = s
|
||||
.Query(q => _queryContainer)
|
||||
.Index(indexer.IndexName)
|
||||
.Sort(r => _sortContainerDescriptor)
|
||||
.From(offset)
|
||||
.Size(_limit);
|
||||
|
||||
if (onlyId)
|
||||
{
|
||||
result = "*" + result + "*";
|
||||
result = result.Source(r => r.Includes(a => a.Field("id")));
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
}
|
||||
|
||||
internal Func<DeleteByQueryDescriptor<T>, IDeleteByQueryRequest> GetDescriptorForDelete(BaseIndexer<T> indexer, bool immediately = true)
|
||||
{
|
||||
return s =>
|
||||
{
|
||||
var result = s
|
||||
.Query(q => _queryContainer)
|
||||
.Index(indexer.IndexName);
|
||||
if (immediately)
|
||||
{
|
||||
result.Refresh();
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
}
|
||||
|
||||
internal Func<UpdateByQueryDescriptor<T>, IUpdateByQueryRequest> GetDescriptorForUpdate(BaseIndexer<T> indexer, Func<ScriptDescriptor, IScript> script, bool immediately = true)
|
||||
{
|
||||
return s =>
|
||||
{
|
||||
var result = s
|
||||
.Query(q => _queryContainer)
|
||||
.Index(indexer.IndexName)
|
||||
.Script(script);
|
||||
|
||||
if (immediately)
|
||||
{
|
||||
result.Refresh();
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
}
|
||||
|
||||
private void Match(Func<Fields> propsFunc, string value)
|
||||
{
|
||||
if (string.IsNullOrEmpty(value))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
public static string ReplaceBackslash(this string value)
|
||||
value = value.PrepareToSearch();
|
||||
|
||||
var props = propsFunc();
|
||||
|
||||
if (IsExactlyPhrase(value))
|
||||
{
|
||||
return value.Replace("\\", "\\\\");
|
||||
_queryContainer = _queryContainer && MultiPhrase(props, value.TrimQuotes());
|
||||
}
|
||||
else if (value.HasOtherLetter() || IsExactly(value))
|
||||
{
|
||||
_queryContainer = _queryContainer && MultiMatch(props, value.TrimQuotes());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IsPhrase(value))
|
||||
{
|
||||
var phrase = value.Split(' ');
|
||||
foreach (var p in phrase)
|
||||
{
|
||||
_queryContainer = _queryContainer && MultiWildCard(props, p.WrapAsterisk());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_queryContainer = _queryContainer && MultiWildCard(props, value.WrapAsterisk());
|
||||
}
|
||||
}
|
||||
|
||||
public static string TrimQuotes(this string value)
|
||||
if (IsExactly(value))
|
||||
{
|
||||
return value.Trim('\"');
|
||||
_queryContainer = _queryContainer || MultiPhrase(props, value);
|
||||
}
|
||||
}
|
||||
|
||||
private QueryContainer Wrap(Field fieldSelector, Func<Field, QueryContainerDescriptor<T>, QueryContainer> selector)
|
||||
{
|
||||
var path = IsNested(fieldSelector);
|
||||
|
||||
if (string.IsNullOrEmpty(path) &&
|
||||
!string.IsNullOrEmpty(fieldSelector.Name) &&
|
||||
fieldSelector.Name.IndexOf(".", StringComparison.InvariantCulture) > 0)
|
||||
{
|
||||
var splitted = fieldSelector.Name.Split(':')[1];
|
||||
path = splitted.Split('.')[0];
|
||||
fieldSelector = new Field(splitted);
|
||||
}
|
||||
|
||||
public static string PrepareToSearch(this string value)
|
||||
if (!string.IsNullOrEmpty(path))
|
||||
{
|
||||
return value.ReplaceBackslash().ToLowerInvariant().Replace('ё', 'е').Replace('Ё', 'Е');
|
||||
}
|
||||
}
|
||||
return _queryContainerDescriptor.Nested(a => a.Query(b => selector(fieldSelector, b)).Path(path));
|
||||
}
|
||||
|
||||
return selector(fieldSelector, _queryContainerDescriptor);
|
||||
}
|
||||
|
||||
private string IsNested(Field selector)
|
||||
{
|
||||
if (!(selector.Expression is LambdaExpression lambdaExpression))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (lambdaExpression.Body is MethodCallExpression methodCallExpression && methodCallExpression.Arguments.Count > 1)
|
||||
{
|
||||
return !(methodCallExpression.Arguments[0] is MemberExpression pathMember)
|
||||
? null
|
||||
: pathMember.Member.Name.ToLowerCamelCase();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private bool IsPhrase(string searchText)
|
||||
{
|
||||
return searchText.Contains(" ") || searchText.Contains("\r\n") || searchText.Contains("\n");
|
||||
}
|
||||
|
||||
private bool IsExactlyPhrase(string searchText)
|
||||
{
|
||||
return IsPhrase(searchText) && IsExactly(searchText);
|
||||
}
|
||||
|
||||
private bool IsExactly(string searchText)
|
||||
{
|
||||
return searchText.StartsWith("\"") && searchText.EndsWith("\"");
|
||||
}
|
||||
|
||||
private QueryContainer MultiMatch(Fields fields, string value)
|
||||
{
|
||||
var qcWildCard = new QueryContainer();
|
||||
|
||||
foreach (var field in fields)
|
||||
{
|
||||
var field1 = field;
|
||||
qcWildCard = qcWildCard || Wrap(field1, (a, w) => w.Match(r => r.Field(a).Query(value.ToLower())));
|
||||
}
|
||||
|
||||
return qcWildCard;
|
||||
}
|
||||
|
||||
private QueryContainer MultiWildCard(Fields fields, string value)
|
||||
{
|
||||
var qcWildCard = new QueryContainer();
|
||||
|
||||
foreach (var field in fields)
|
||||
{
|
||||
qcWildCard = qcWildCard || Wrap(field, (a, w) => w.Wildcard(r => r.Field(a).Value(value)));
|
||||
}
|
||||
|
||||
return qcWildCard;
|
||||
}
|
||||
|
||||
private QueryContainer MultiPhrase(Fields fields, string value)
|
||||
{
|
||||
var qcWildCard = new QueryContainer();
|
||||
|
||||
foreach (var field in fields)
|
||||
{
|
||||
qcWildCard = qcWildCard || Wrap(field, (a, w) => w.MatchPhrase(r => r.Field(a).Query(value.ToLower())));
|
||||
}
|
||||
|
||||
return qcWildCard;
|
||||
}
|
||||
}
|
||||
|
||||
internal static class StringExtension
|
||||
{
|
||||
private static bool Any(this string value, UnicodeCategory category)
|
||||
{
|
||||
return !string.IsNullOrWhiteSpace(value)
|
||||
&& value.Any(@char => char.GetUnicodeCategory(@char) == category);
|
||||
}
|
||||
|
||||
public static bool HasOtherLetter(this string value)
|
||||
{
|
||||
return value.Any(UnicodeCategory.OtherLetter);
|
||||
}
|
||||
|
||||
public static string WrapAsterisk(this string value)
|
||||
{
|
||||
var result = value;
|
||||
|
||||
if (!value.Contains("*") && !value.Contains("?"))
|
||||
{
|
||||
result = "*" + result + "*";
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static string ReplaceBackslash(this string value)
|
||||
{
|
||||
return value.Replace("\\", "\\\\");
|
||||
}
|
||||
|
||||
public static string TrimQuotes(this string value)
|
||||
{
|
||||
return value.Trim('\"');
|
||||
}
|
||||
|
||||
public static string PrepareToSearch(this string value)
|
||||
{
|
||||
return value.ReplaceBackslash().ToLowerInvariant().Replace('ё', 'е').Replace('Ё', 'Е');
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,7 @@
|
||||
namespace ASC.ElasticSearch.Core
|
||||
namespace ASC.ElasticSearch.Core;
|
||||
|
||||
public class State
|
||||
{
|
||||
public class State
|
||||
{
|
||||
public string Indexing { get; set; }
|
||||
public DateTime? LastIndexed { get; set; }
|
||||
}
|
||||
public string Indexing { get; set; }
|
||||
public DateTime? LastIndexed { get; set; }
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -23,41 +23,41 @@
|
||||
*
|
||||
*/
|
||||
|
||||
namespace ASC.ElasticSearch
|
||||
namespace ASC.ElasticSearch;
|
||||
|
||||
[Singletone]
|
||||
public class Client
|
||||
{
|
||||
[Singletone]
|
||||
public class Client
|
||||
public ElasticClient Instance
|
||||
{
|
||||
public ElasticClient Instance
|
||||
get
|
||||
{
|
||||
get
|
||||
if (_client != null)
|
||||
{
|
||||
return _client;
|
||||
}
|
||||
|
||||
lock (_locker)
|
||||
{
|
||||
if (_client != null)
|
||||
{
|
||||
return _client;
|
||||
}
|
||||
|
||||
lock (_locker)
|
||||
using var scope = _serviceProvider.CreateScope();
|
||||
var CoreConfiguration = _serviceProvider.GetService<CoreConfiguration>();
|
||||
var launchSettings = CoreConfiguration.GetSection<Settings>(Tenant.DEFAULT_TENANT) ?? _settings;
|
||||
|
||||
var uri = new Uri(string.Format("{0}://{1}:{2}", launchSettings.Scheme, launchSettings.Host, launchSettings.Port));
|
||||
var settings = new ConnectionSettings(new SingleNodeConnectionPool(uri))
|
||||
.RequestTimeout(TimeSpan.FromMinutes(5))
|
||||
.MaximumRetries(10)
|
||||
.ThrowExceptions();
|
||||
|
||||
if (_logger.IsTraceEnabled)
|
||||
{
|
||||
if (_client != null)
|
||||
settings.DisableDirectStreaming().PrettyJson().EnableDebugMode(r =>
|
||||
{
|
||||
return _client;
|
||||
}
|
||||
|
||||
using var scope = _serviceProvider.CreateScope();
|
||||
var CoreConfiguration = _serviceProvider.GetService<CoreConfiguration>();
|
||||
var launchSettings = CoreConfiguration.GetSection<Settings>(Tenant.DEFAULT_TENANT) ?? _settings;
|
||||
|
||||
var uri = new Uri(string.Format("{0}://{1}:{2}", launchSettings.Scheme, launchSettings.Host, launchSettings.Port));
|
||||
var settings = new ConnectionSettings(new SingleNodeConnectionPool(uri))
|
||||
.RequestTimeout(TimeSpan.FromMinutes(5))
|
||||
.MaximumRetries(10)
|
||||
.ThrowExceptions();
|
||||
|
||||
if (_logger.IsTraceEnabled)
|
||||
{
|
||||
settings.DisableDirectStreaming().PrettyJson().EnableDebugMode(r =>
|
||||
{
|
||||
//Log.Trace(r.DebugInformation);
|
||||
|
||||
//if (r.RequestBodyInBytes != null)
|
||||
@ -66,65 +66,64 @@ namespace ASC.ElasticSearch
|
||||
//}
|
||||
|
||||
if (r.HttpStatusCode != null && (r.HttpStatusCode == 403 || r.HttpStatusCode == 500) && r.ResponseBodyInBytes != null)
|
||||
{
|
||||
_logger.TraceFormat("Response: {0}", Encoding.UTF8.GetString(r.ResponseBodyInBytes));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (Ping(new ElasticClient(settings)))
|
||||
{
|
||||
_client = new ElasticClient(settings);
|
||||
|
||||
_client.Ingest.PutPipeline("attachments", p => p
|
||||
.Processors(pp => pp
|
||||
.Attachment<Attachment>(a => a.Field("document.data").TargetField("document.attachment"))
|
||||
));
|
||||
_logger.TraceFormat("Response: {0}", Encoding.UTF8.GetString(r.ResponseBodyInBytes));
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.Error(e);
|
||||
}
|
||||
|
||||
return _client;
|
||||
});
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (Ping(new ElasticClient(settings)))
|
||||
{
|
||||
_client = new ElasticClient(settings);
|
||||
|
||||
_client.Ingest.PutPipeline("attachments", p => p
|
||||
.Processors(pp => pp
|
||||
.Attachment<Attachment>(a => a.Field("document.data").TargetField("document.attachment"))
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.Error(e);
|
||||
}
|
||||
|
||||
return _client;
|
||||
}
|
||||
}
|
||||
|
||||
private static volatile ElasticClient _client;
|
||||
private static readonly object _locker = new object();
|
||||
private readonly ILog _logger;
|
||||
private readonly Settings _settings;
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
|
||||
public Client(IOptionsMonitor<ILog> option, IServiceProvider serviceProvider, Settings settings)
|
||||
{
|
||||
_logger = option.Get("ASC.Indexer");
|
||||
_settings = settings;
|
||||
_serviceProvider = serviceProvider;
|
||||
}
|
||||
|
||||
public bool Ping()
|
||||
{
|
||||
return Ping(Instance);
|
||||
}
|
||||
|
||||
private bool Ping(ElasticClient elasticClient)
|
||||
{
|
||||
if (elasticClient == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var result = elasticClient.Ping(new PingRequest());
|
||||
|
||||
_logger.DebugFormat("Ping {0}", result.DebugInformation);
|
||||
|
||||
return result.IsValid;
|
||||
}
|
||||
}
|
||||
|
||||
private static volatile ElasticClient _client;
|
||||
private static readonly object _locker = new object();
|
||||
private readonly ILog _logger;
|
||||
private readonly Settings _settings;
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
|
||||
public Client(IOptionsMonitor<ILog> option, IServiceProvider serviceProvider, Settings settings)
|
||||
{
|
||||
_logger = option.Get("ASC.Indexer");
|
||||
_settings = settings;
|
||||
_serviceProvider = serviceProvider;
|
||||
}
|
||||
|
||||
public bool Ping()
|
||||
{
|
||||
return Ping(Instance);
|
||||
}
|
||||
|
||||
private bool Ping(ElasticClient elasticClient)
|
||||
{
|
||||
if (elasticClient == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var result = elasticClient.Ping(new PingRequest());
|
||||
|
||||
_logger.DebugFormat("Ping {0}", result.DebugInformation);
|
||||
|
||||
return result.IsValid;
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -23,14 +23,13 @@
|
||||
*
|
||||
*/
|
||||
|
||||
namespace ASC.ElasticSearch
|
||||
namespace ASC.ElasticSearch;
|
||||
|
||||
public interface IIndexer
|
||||
{
|
||||
public interface IIndexer
|
||||
{
|
||||
string IndexName { get; }
|
||||
string IndexName { get; }
|
||||
|
||||
void IndexAll();
|
||||
void IndexAll();
|
||||
|
||||
Task ReIndex();
|
||||
}
|
||||
Task ReIndex();
|
||||
}
|
||||
|
@ -23,115 +23,98 @@
|
||||
*
|
||||
*/
|
||||
|
||||
namespace ASC.ElasticSearch
|
||||
namespace ASC.ElasticSearch;
|
||||
|
||||
[Singletone(Additional = typeof(ServiceLauncherExtension))]
|
||||
public class ElasticSearchIndexService : IHostedService, IDisposable
|
||||
{
|
||||
[Singletone(Additional = typeof(ServiceLauncherExtension))]
|
||||
public class ElasticSearchIndexService : IHostedService, IDisposable
|
||||
private readonly ILog _logger;
|
||||
private readonly ICacheNotify<AscCacheItem> _notify;
|
||||
private readonly ICacheNotify<IndexAction> _indexNotify;
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private readonly CancellationTokenSource _cancellationTokenSource;
|
||||
private readonly TimeSpan _period;
|
||||
private Timer _timer = null!;
|
||||
private bool _isStarted;
|
||||
|
||||
public ElasticSearchIndexService(
|
||||
IOptionsMonitor<ILog> options,
|
||||
ICacheNotify<AscCacheItem> notify,
|
||||
ICacheNotify<IndexAction> indexNotify,
|
||||
IServiceProvider serviceProvider,
|
||||
Settings settings)
|
||||
{
|
||||
private readonly ILog _logger;
|
||||
private readonly ICacheNotify<AscCacheItem> _notify;
|
||||
private readonly ICacheNotify<IndexAction> _indexNotify;
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private readonly CancellationTokenSource _cancellationTokenSource;
|
||||
private readonly TimeSpan _period;
|
||||
private Timer _timer = null!;
|
||||
private bool _isStarted;
|
||||
_logger = options.Get("ASC.Indexer");
|
||||
_notify = notify;
|
||||
_indexNotify = indexNotify;
|
||||
_serviceProvider = serviceProvider;
|
||||
_cancellationTokenSource = new CancellationTokenSource();
|
||||
_period = TimeSpan.FromMinutes(settings.Period.Value);
|
||||
}
|
||||
|
||||
public ElasticSearchIndexService(
|
||||
IOptionsMonitor<ILog> options,
|
||||
ICacheNotify<AscCacheItem> notify,
|
||||
ICacheNotify<IndexAction> indexNotify,
|
||||
IServiceProvider serviceProvider,
|
||||
Settings settings)
|
||||
public Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
_logger.Info("ElasticSearch Index Service running.");
|
||||
|
||||
try
|
||||
{
|
||||
_logger = options.Get("ASC.Indexer");
|
||||
_notify = notify;
|
||||
_indexNotify = indexNotify;
|
||||
_serviceProvider = serviceProvider;
|
||||
_cancellationTokenSource = new CancellationTokenSource();
|
||||
_period = TimeSpan.FromMinutes(settings.Period.Value);
|
||||
}
|
||||
|
||||
public Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
_logger.Info("ElasticSearch Index Service running.");
|
||||
|
||||
try
|
||||
_notify.Subscribe(async (item) =>
|
||||
{
|
||||
_notify.Subscribe(async (item) =>
|
||||
while (_isStarted)
|
||||
{
|
||||
while (_isStarted)
|
||||
{
|
||||
await Task.Delay(10000);
|
||||
}
|
||||
IndexAll(true);
|
||||
}, CacheNotifyAction.Any);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.Error("Subscribe on start", e);
|
||||
}
|
||||
|
||||
var task = new Task(async () =>
|
||||
{
|
||||
using var scope = _serviceProvider.CreateScope();
|
||||
var scopeClass = scope.ServiceProvider.GetService<ServiceLauncherScope>();
|
||||
var (factoryIndexer, service) = scopeClass;
|
||||
while (!factoryIndexer.CheckState(false))
|
||||
{
|
||||
if (_cancellationTokenSource.IsCancellationRequested)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
await Task.Delay(10000);
|
||||
}
|
||||
|
||||
service.Subscribe();
|
||||
_timer = new Timer(_ => IndexAll(), null, TimeSpan.Zero, TimeSpan.Zero);
|
||||
|
||||
}, _cancellationTokenSource.Token, TaskCreationOptions.LongRunning);
|
||||
|
||||
task.ConfigureAwait(false);
|
||||
task.Start();
|
||||
|
||||
return Task.CompletedTask;
|
||||
IndexAll(true);
|
||||
}, CacheNotifyAction.Any);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.Error("Subscribe on start", e);
|
||||
}
|
||||
|
||||
public Task StopAsync(CancellationToken cancellationToken)
|
||||
var task = new Task(async () =>
|
||||
{
|
||||
_logger.Info("ElasticSearch Index Service is stopping.");
|
||||
|
||||
_isStarted = false;
|
||||
|
||||
_timer?.Change(Timeout.Infinite, 0);
|
||||
|
||||
_cancellationTokenSource.Cancel();
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public void IndexProduct(IFactoryIndexer product, bool reindex)
|
||||
{
|
||||
if (reindex)
|
||||
using var scope = _serviceProvider.CreateScope();
|
||||
var scopeClass = scope.ServiceProvider.GetService<ServiceLauncherScope>();
|
||||
var (factoryIndexer, service) = scopeClass;
|
||||
while (!factoryIndexer.CheckState(false))
|
||||
{
|
||||
try
|
||||
if (_cancellationTokenSource.IsCancellationRequested)
|
||||
{
|
||||
if (!_isStarted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
_logger.DebugFormat("Product reindex {0}", product.IndexName);
|
||||
product.ReIndex();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.Error(e);
|
||||
_logger.ErrorFormat("Product reindex {0}", product.IndexName);
|
||||
}
|
||||
await Task.Delay(10000);
|
||||
}
|
||||
|
||||
service.Subscribe();
|
||||
_timer = new Timer(_ => IndexAll(), null, TimeSpan.Zero, TimeSpan.Zero);
|
||||
|
||||
}, _cancellationTokenSource.Token, TaskCreationOptions.LongRunning);
|
||||
|
||||
task.ConfigureAwait(false);
|
||||
task.Start();
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task StopAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
_logger.Info("ElasticSearch Index Service is stopping.");
|
||||
|
||||
_isStarted = false;
|
||||
|
||||
_timer?.Change(Timeout.Infinite, 0);
|
||||
|
||||
_cancellationTokenSource.Cancel();
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public void IndexProduct(IFactoryIndexer product, bool reindex)
|
||||
{
|
||||
if (reindex)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!_isStarted)
|
||||
@ -139,85 +122,101 @@ namespace ASC.ElasticSearch
|
||||
return;
|
||||
}
|
||||
|
||||
_logger.DebugFormat("Product {0}", product.IndexName);
|
||||
_indexNotify.Publish(new IndexAction() { Indexing = product.IndexName, LastIndexed = 0 }, CacheNotifyAction.Any);
|
||||
product.IndexAll();
|
||||
_logger.DebugFormat("Product reindex {0}", product.IndexName);
|
||||
product.ReIndex();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.Error(e);
|
||||
_logger.ErrorFormat("Product {0}", product.IndexName);
|
||||
_logger.ErrorFormat("Product reindex {0}", product.IndexName);
|
||||
}
|
||||
}
|
||||
|
||||
private void IndexAll(bool reindex = false)
|
||||
try
|
||||
{
|
||||
try
|
||||
if (!_isStarted)
|
||||
{
|
||||
_timer.Change(Timeout.Infinite, Timeout.Infinite);
|
||||
_isStarted = true;
|
||||
return;
|
||||
}
|
||||
|
||||
using (var scope = _serviceProvider.CreateScope())
|
||||
_logger.DebugFormat("Product {0}", product.IndexName);
|
||||
_indexNotify.Publish(new IndexAction() { Indexing = product.IndexName, LastIndexed = 0 }, CacheNotifyAction.Any);
|
||||
product.IndexAll();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.Error(e);
|
||||
_logger.ErrorFormat("Product {0}", product.IndexName);
|
||||
}
|
||||
}
|
||||
|
||||
private void IndexAll(bool reindex = false)
|
||||
{
|
||||
try
|
||||
{
|
||||
_timer.Change(Timeout.Infinite, Timeout.Infinite);
|
||||
_isStarted = true;
|
||||
|
||||
using (var scope = _serviceProvider.CreateScope())
|
||||
{
|
||||
var wrappers = scope.ServiceProvider.GetService<IEnumerable<IFactoryIndexer>>();
|
||||
|
||||
Parallel.ForEach(wrappers, wrapper =>
|
||||
{
|
||||
var wrappers = scope.ServiceProvider.GetService<IEnumerable<IFactoryIndexer>>();
|
||||
|
||||
Parallel.ForEach(wrappers, wrapper =>
|
||||
using (var scope = _serviceProvider.CreateScope())
|
||||
{
|
||||
using (var scope = _serviceProvider.CreateScope())
|
||||
{
|
||||
var w = (IFactoryIndexer)scope.ServiceProvider.GetService(wrapper.GetType());
|
||||
IndexProduct(w, reindex);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
_timer.Change(_period, _period);
|
||||
_indexNotify.Publish(new IndexAction() { Indexing = "", LastIndexed = DateTime.Now.Ticks }, CacheNotifyAction.Any);
|
||||
_isStarted = false;
|
||||
var w = (IFactoryIndexer)scope.ServiceProvider.GetService(wrapper.GetType());
|
||||
IndexProduct(w, reindex);
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.Fatal("IndexAll", e);
|
||||
|
||||
throw;
|
||||
}
|
||||
_timer.Change(_period, _period);
|
||||
_indexNotify.Publish(new IndexAction() { Indexing = "", LastIndexed = DateTime.Now.Ticks }, CacheNotifyAction.Any);
|
||||
_isStarted = false;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
catch (Exception e)
|
||||
{
|
||||
var handle = new AutoResetEvent(false);
|
||||
_logger.Fatal("IndexAll", e);
|
||||
|
||||
if (!(bool)_timer?.Dispose(handle))
|
||||
throw new Exception("Timer already disposed");
|
||||
|
||||
handle.WaitOne();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
[Scope]
|
||||
public class ServiceLauncherScope
|
||||
public void Dispose()
|
||||
{
|
||||
private readonly FactoryIndexer _factoryIndexer;
|
||||
private readonly Service.ElasticSearchService _service;
|
||||
var handle = new AutoResetEvent(false);
|
||||
|
||||
public ServiceLauncherScope(FactoryIndexer factoryIndexer, Service.ElasticSearchService service)
|
||||
{
|
||||
_factoryIndexer = factoryIndexer;
|
||||
_service = service;
|
||||
}
|
||||
if (!(bool)_timer?.Dispose(handle))
|
||||
throw new Exception("Timer already disposed");
|
||||
|
||||
public void Deconstruct(out FactoryIndexer factoryIndexer, out Service.ElasticSearchService service)
|
||||
{
|
||||
factoryIndexer = _factoryIndexer;
|
||||
service = _service;
|
||||
}
|
||||
}
|
||||
|
||||
public class ServiceLauncherExtension
|
||||
{
|
||||
public static void Register(DIHelper services)
|
||||
{
|
||||
services.TryAdd<ServiceLauncherScope>();
|
||||
}
|
||||
handle.WaitOne();
|
||||
}
|
||||
}
|
||||
|
||||
[Scope]
|
||||
public class ServiceLauncherScope
|
||||
{
|
||||
private readonly FactoryIndexer _factoryIndexer;
|
||||
private readonly Service.ElasticSearchService _service;
|
||||
|
||||
public ServiceLauncherScope(FactoryIndexer factoryIndexer, Service.ElasticSearchService service)
|
||||
{
|
||||
_factoryIndexer = factoryIndexer;
|
||||
_service = service;
|
||||
}
|
||||
|
||||
public void Deconstruct(out FactoryIndexer factoryIndexer, out Service.ElasticSearchService service)
|
||||
{
|
||||
factoryIndexer = _factoryIndexer;
|
||||
service = _service;
|
||||
}
|
||||
}
|
||||
|
||||
public class ServiceLauncherExtension
|
||||
{
|
||||
public static void Register(DIHelper services)
|
||||
{
|
||||
services.TryAdd<ServiceLauncherScope>();
|
||||
}
|
||||
}
|
||||
|
@ -23,100 +23,99 @@
|
||||
*
|
||||
*/
|
||||
|
||||
namespace ASC.ElasticSearch.Service
|
||||
namespace ASC.ElasticSearch.Service;
|
||||
|
||||
[Singletone(Additional = typeof(ServiceExtension))]
|
||||
public class ElasticSearchService
|
||||
{
|
||||
[Singletone(Additional = typeof(ServiceExtension))]
|
||||
public class ElasticSearchService
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private readonly ICacheNotify<ReIndexAction> _cacheNotify;
|
||||
|
||||
public ElasticSearchService(IServiceProvider serviceProvider, ICacheNotify<ReIndexAction> cacheNotify)
|
||||
{
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private readonly ICacheNotify<ReIndexAction> _cacheNotify;
|
||||
|
||||
public ElasticSearchService(IServiceProvider serviceProvider, ICacheNotify<ReIndexAction> cacheNotify)
|
||||
{
|
||||
_serviceProvider = serviceProvider;
|
||||
_cacheNotify = cacheNotify;
|
||||
}
|
||||
|
||||
public void Subscribe()
|
||||
{
|
||||
_cacheNotify.Subscribe((a) =>
|
||||
{
|
||||
ReIndex(a.Names.ToList(), a.Tenant);
|
||||
}, CacheNotifyAction.Any);
|
||||
}
|
||||
|
||||
public bool Support(string table)
|
||||
{
|
||||
return _serviceProvider.GetService<IEnumerable<IFactoryIndexer>>().Any(r => r.IndexName == table);
|
||||
}
|
||||
|
||||
public void ReIndex(List<string> toReIndex, int tenant)
|
||||
{
|
||||
var allItems = _serviceProvider.GetService<IEnumerable<IFactoryIndexer>>().ToList();
|
||||
var tasks = new List<Task>(toReIndex.Count);
|
||||
|
||||
foreach (var item in toReIndex)
|
||||
{
|
||||
var index = allItems.FirstOrDefault(r => r.IndexName == item);
|
||||
if (index == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var generic = typeof(BaseIndexer<>);
|
||||
var instance = (IIndexer)Activator.CreateInstance(generic.MakeGenericType(index.GetType()), index);
|
||||
tasks.Add(instance.ReIndex());
|
||||
}
|
||||
|
||||
if (!tasks.Any())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Task.WhenAll(tasks).ContinueWith(r =>
|
||||
{
|
||||
using var scope = _serviceProvider.CreateScope();
|
||||
|
||||
var scopeClass = scope.ServiceProvider.GetService<ServiceScope>();
|
||||
var (tenantManager, settingsManager) = scopeClass;
|
||||
tenantManager.SetCurrentTenant(tenant);
|
||||
settingsManager.ClearCache<SearchSettings>();
|
||||
});
|
||||
}
|
||||
//public State GetState()
|
||||
//{
|
||||
// return new State
|
||||
// {
|
||||
// Indexing = Launcher.Indexing,
|
||||
// LastIndexed = Launcher.LastIndexed
|
||||
// };
|
||||
//}
|
||||
_serviceProvider = serviceProvider;
|
||||
_cacheNotify = cacheNotify;
|
||||
}
|
||||
|
||||
[Scope]
|
||||
public class ServiceScope
|
||||
public void Subscribe()
|
||||
{
|
||||
private readonly TenantManager _tenantManager;
|
||||
private readonly SettingsManager _settingsManager;
|
||||
|
||||
public ServiceScope(TenantManager tenantManager, SettingsManager settingsManager)
|
||||
_cacheNotify.Subscribe((a) =>
|
||||
{
|
||||
_tenantManager = tenantManager;
|
||||
_settingsManager = settingsManager;
|
||||
}
|
||||
|
||||
public void Deconstruct(out TenantManager tenantManager, out SettingsManager settingsManager)
|
||||
{
|
||||
tenantManager = _tenantManager;
|
||||
settingsManager = _settingsManager;
|
||||
}
|
||||
ReIndex(a.Names.ToList(), a.Tenant);
|
||||
}, CacheNotifyAction.Any);
|
||||
}
|
||||
|
||||
internal class ServiceExtension
|
||||
public bool Support(string table)
|
||||
{
|
||||
public static void Register(DIHelper services)
|
||||
return _serviceProvider.GetService<IEnumerable<IFactoryIndexer>>().Any(r => r.IndexName == table);
|
||||
}
|
||||
|
||||
public void ReIndex(List<string> toReIndex, int tenant)
|
||||
{
|
||||
var allItems = _serviceProvider.GetService<IEnumerable<IFactoryIndexer>>().ToList();
|
||||
var tasks = new List<Task>(toReIndex.Count);
|
||||
|
||||
foreach (var item in toReIndex)
|
||||
{
|
||||
services.TryAdd<ServiceScope>();
|
||||
var index = allItems.FirstOrDefault(r => r.IndexName == item);
|
||||
if (index == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var generic = typeof(BaseIndexer<>);
|
||||
var instance = (IIndexer)Activator.CreateInstance(generic.MakeGenericType(index.GetType()), index);
|
||||
tasks.Add(instance.ReIndex());
|
||||
}
|
||||
|
||||
if (!tasks.Any())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Task.WhenAll(tasks).ContinueWith(r =>
|
||||
{
|
||||
using var scope = _serviceProvider.CreateScope();
|
||||
|
||||
var scopeClass = scope.ServiceProvider.GetService<ServiceScope>();
|
||||
var (tenantManager, settingsManager) = scopeClass;
|
||||
tenantManager.SetCurrentTenant(tenant);
|
||||
settingsManager.ClearCache<SearchSettings>();
|
||||
});
|
||||
}
|
||||
//public State GetState()
|
||||
//{
|
||||
// return new State
|
||||
// {
|
||||
// Indexing = Launcher.Indexing,
|
||||
// LastIndexed = Launcher.LastIndexed
|
||||
// };
|
||||
//}
|
||||
}
|
||||
|
||||
[Scope]
|
||||
public class ServiceScope
|
||||
{
|
||||
private readonly TenantManager _tenantManager;
|
||||
private readonly SettingsManager _settingsManager;
|
||||
|
||||
public ServiceScope(TenantManager tenantManager, SettingsManager settingsManager)
|
||||
{
|
||||
_tenantManager = tenantManager;
|
||||
_settingsManager = settingsManager;
|
||||
}
|
||||
|
||||
public void Deconstruct(out TenantManager tenantManager, out SettingsManager settingsManager)
|
||||
{
|
||||
tenantManager = _tenantManager;
|
||||
settingsManager = _settingsManager;
|
||||
}
|
||||
}
|
||||
|
||||
internal class ServiceExtension
|
||||
{
|
||||
public static void Register(DIHelper services)
|
||||
{
|
||||
services.TryAdd<ServiceScope>();
|
||||
}
|
||||
}
|
||||
|
@ -23,64 +23,63 @@
|
||||
*
|
||||
*/
|
||||
|
||||
namespace ASC.ElasticSearch.Service
|
||||
namespace ASC.ElasticSearch.Service;
|
||||
|
||||
[Singletone]
|
||||
public class Settings
|
||||
{
|
||||
[Singletone]
|
||||
public class Settings
|
||||
public string Host
|
||||
{
|
||||
public string Host
|
||||
{
|
||||
get => _host ?? "localhost";
|
||||
set => _host = value;
|
||||
}
|
||||
public int? Port
|
||||
{
|
||||
get => _port ?? 9200;
|
||||
set => _port = value;
|
||||
}
|
||||
public string Scheme
|
||||
{
|
||||
get => _scheme ?? "http";
|
||||
set => _scheme = value;
|
||||
}
|
||||
public int? Period
|
||||
{
|
||||
get => _period ?? 1;
|
||||
set => _period = value;
|
||||
}
|
||||
public long? MaxContentLength
|
||||
{
|
||||
get => _maxContentLength ?? 100 * 1024 * 1024L;
|
||||
set => _maxContentLength = value;
|
||||
}
|
||||
public long? MaxFileSize
|
||||
{
|
||||
get => _maxFileSize ?? 10 * 1024 * 1024L;
|
||||
set => _maxFileSize = value;
|
||||
}
|
||||
public int? Threads
|
||||
{
|
||||
get => _threads ?? 1;
|
||||
set => _threads = value;
|
||||
}
|
||||
public bool? HttpCompression
|
||||
{
|
||||
get => _httpCompression ?? true;
|
||||
set => _httpCompression = value;
|
||||
}
|
||||
|
||||
private string _host;
|
||||
private int? _port;
|
||||
private string _scheme;
|
||||
private int? _period;
|
||||
private long? _maxContentLength;
|
||||
private long? _maxFileSize;
|
||||
private int? _threads;
|
||||
private bool? _httpCompression;
|
||||
|
||||
public Settings(ConfigurationExtension configuration)
|
||||
{
|
||||
configuration.GetSetting("elastic", this);
|
||||
}
|
||||
get => _host ?? "localhost";
|
||||
set => _host = value;
|
||||
}
|
||||
}
|
||||
public int? Port
|
||||
{
|
||||
get => _port ?? 9200;
|
||||
set => _port = value;
|
||||
}
|
||||
public string Scheme
|
||||
{
|
||||
get => _scheme ?? "http";
|
||||
set => _scheme = value;
|
||||
}
|
||||
public int? Period
|
||||
{
|
||||
get => _period ?? 1;
|
||||
set => _period = value;
|
||||
}
|
||||
public long? MaxContentLength
|
||||
{
|
||||
get => _maxContentLength ?? 100 * 1024 * 1024L;
|
||||
set => _maxContentLength = value;
|
||||
}
|
||||
public long? MaxFileSize
|
||||
{
|
||||
get => _maxFileSize ?? 10 * 1024 * 1024L;
|
||||
set => _maxFileSize = value;
|
||||
}
|
||||
public int? Threads
|
||||
{
|
||||
get => _threads ?? 1;
|
||||
set => _threads = value;
|
||||
}
|
||||
public bool? HttpCompression
|
||||
{
|
||||
get => _httpCompression ?? true;
|
||||
set => _httpCompression = value;
|
||||
}
|
||||
|
||||
private string _host;
|
||||
private int? _port;
|
||||
private string _scheme;
|
||||
private int? _period;
|
||||
private long? _maxContentLength;
|
||||
private long? _maxFileSize;
|
||||
private int? _threads;
|
||||
private bool? _httpCompression;
|
||||
|
||||
public Settings(ConfigurationExtension configuration)
|
||||
{
|
||||
configuration.GetSetting("elastic", this);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user