protected async Task <T> FindOneAsync(OneOptions options)
        {
            if (options == null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            if (EnableCache && options.UseCache)
            {
                var cacheValue = await Cache.GetAsync <T>(GetScopedCacheKey(options.CacheKey)).AnyContext();

#if DEBUG
                Logger.Trace().Message("Cache {0}: type={1}", cacheValue.HasValue ? "hit" : "miss", _entityType).Write();
#endif
                if (cacheValue.HasValue)
                {
                    return(cacheValue.Value);
                }
            }

            var searchDescriptor = new SearchDescriptor <T>().Query(options.GetElasticSearchQuery <T>(_supportsSoftDeletes)).Size(1);
            if (options.Fields.Count > 0)
            {
                searchDescriptor.Source(s => s.Include(options.Fields.ToArray()));
            }
            else
            {
                searchDescriptor.Source(s => s.Exclude("idx"));
            }

            var elasticSearchOptions = options as ElasticSearchOptions <T>;
            searchDescriptor.Indices(elasticSearchOptions != null && elasticSearchOptions.Indices.Any() ? elasticSearchOptions.Indices.ToArray() : GetIndices());

            if (elasticSearchOptions != null && elasticSearchOptions.SortBy.Count > 0)
            {
                foreach (var sort in elasticSearchOptions.SortBy)
                {
                    searchDescriptor.Sort(sort);
                }
            }

#if DEBUG
            _elasticClient.EnableTrace();
            var sw = Stopwatch.StartNew();
#endif
            var results = await _elasticClient.SearchAsync <T>(searchDescriptor).AnyContext();

#if DEBUG
            sw.Stop();
            _elasticClient.DisableTrace();
            Logger.Trace().Message($"FindOneAsync: {sw.ElapsedMilliseconds}ms, Elastic Took {results.ElapsedMilliseconds}ms, Serialization Took {results.ConnectionStatus.Metrics.SerializationTime}ms, Deserialization Took {results.ConnectionStatus.Metrics.DeserializationTime}ms").Write();
#endif
            var result = results.Documents.FirstOrDefault();
            if (EnableCache && options.UseCache && result != null)
            {
                await Cache.SetAsync(GetScopedCacheKey(options.CacheKey), result, options.GetCacheExpirationDate()).AnyContext();
            }

            return(result);
        }
        protected async Task <bool> ExistsAsync(OneOptions options)
        {
            if (options == null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            options.Fields.Add("id");
            var searchDescriptor = new SearchDescriptor <T>().Query(options.GetElasticSearchQuery <T>(_supportsSoftDeletes)).Size(1);

            var elasticSearchOptions = options as ElasticSearchOptions <T>;

            searchDescriptor.Indices(elasticSearchOptions != null && elasticSearchOptions.Indices.Any()
                ? elasticSearchOptions.Indices.ToArray()
                : GetIndices());
            if (elasticSearchOptions != null && elasticSearchOptions.SortBy.Count > 0)
            {
                foreach (var sort in elasticSearchOptions.SortBy)
                {
                    searchDescriptor.Sort(sort);
                }
            }

#if DEBUG
            _elasticClient.EnableTrace();
            var sw = Stopwatch.StartNew();
#endif
            var results = await _elasticClient.SearchAsync <T>(searchDescriptor).AnyContext();

#if DEBUG
            sw.Stop();
            _elasticClient.DisableTrace();
            Logger.Trace().Message($"ExistsAsync: {sw.ElapsedMilliseconds}ms, Elastic Took {results.ElapsedMilliseconds}ms, Serialization Took {results.ConnectionStatus.Metrics.SerializationTime}ms, Deserialization Took {results.ConnectionStatus.Metrics.DeserializationTime}ms").Write();
#endif

            return(results.HitsMetaData.Total > 0);
        }