public async Task <IReadOnlyCollection <T> > GetByIdsAsync(Ids ids, ICommandOptions options = null) { var idList = ids?.Distinct().Where(i => !String.IsNullOrEmpty(i)).ToList(); if (idList == null || idList.Count == 0) { return(EmptyList); } if (!HasIdentity) { throw new NotSupportedException("Model type must implement IIdentity."); } var hits = new List <T>(); if (IsCacheEnabled && options.ShouldReadCache()) { var cacheHits = await Cache.GetAllAsync <T>(idList.Select(id => id.Value)).AnyContext(); hits.AddRange(cacheHits.Where(kvp => kvp.Value.HasValue).Select(kvp => kvp.Value.Value)); } var itemsToFind = idList.Except(hits.OfType <IIdentity>().Select(i => (Id)i.Id)).ToList(); if (itemsToFind.Count == 0) { return(hits.AsReadOnly()); } var multiGet = new MultiGetDescriptor(); foreach (var id in itemsToFind.Where(i => i.Routing != null || !HasParent)) { multiGet.Get <T>(f => { f.Id(id.Value).Index(GetIndexById(id)).Type(ElasticType.Name); if (id.Routing != null) { f.Routing(id.Routing); } return(f); }); } var multiGetResults = await _client.MultiGetAsync(multiGet).AnyContext(); _logger.Trace(() => multiGetResults.GetRequest()); foreach (var doc in multiGetResults.Documents) { if (!doc.Found) { continue; } hits.Add(((IMultiGetHit <T>)doc).ToFindHit().Document); itemsToFind.Remove(doc.Id); } // fallback to doing a find if (itemsToFind.Count > 0 && (HasParent || HasMultipleIndexes)) { var response = await FindAsync(q => q.Id(itemsToFind.Select(id => id.Value)), o => o.PageLimit(1000)).AnyContext(); do { if (response.Hits.Count > 0) { hits.AddRange(response.Hits.Where(h => h.Document != null).Select(h => h.Document)); } } while (await response.NextPageAsync().AnyContext()); } if (IsCacheEnabled && options.ShouldUseCache()) { foreach (var item in hits.OfType <IIdentity>()) { await Cache.SetAsync(item.Id, item, options.GetExpiresIn()).AnyContext(); } } return(hits.AsReadOnly()); }
public virtual async Task <IReadOnlyCollection <T> > GetByIdsAsync(Ids ids, ICommandOptions options = null) { var idList = ids?.Distinct().Where(i => !String.IsNullOrEmpty(i)).ToList(); if (idList == null || idList.Count == 0) { return(EmptyList); } if (!HasIdentity) { throw new NotSupportedException("Model type must implement IIdentity."); } options = ConfigureOptions(options.As <T>()); if (IsCacheEnabled && options.HasCacheKey()) { throw new ArgumentException("Cache key can't be set when calling GetByIds"); } var hits = new List <FindHit <T> >(); if (IsCacheEnabled && options.ShouldReadCache()) { hits.AddRange(await GetCachedFindHit(idList).AnyContext()); } var itemsToFind = idList.Except(hits.Select(i => (Id)i.Id)).ToList(); if (itemsToFind.Count == 0) { return(hits.Where(h => h.Document != null && ShouldReturnDocument(h.Document, options)).Select(h => h.Document).ToList().AsReadOnly()); } var multiGet = new MultiGetDescriptor(); foreach (var id in itemsToFind.Where(i => i.Routing != null || !HasParent)) { multiGet.Get <T>(f => { f.Id(id.Value).Index(ElasticIndex.GetIndex(id)); if (id.Routing != null) { f.Routing(id.Routing); } return(f); }); } var multiGetResults = await _client.MultiGetAsync(multiGet).AnyContext(); _logger.LogRequest(multiGetResults, options.GetQueryLogLevel()); foreach (var doc in multiGetResults.Hits) { hits.Add(((IMultiGetHit <T>)doc).ToFindHit()); itemsToFind.Remove(new Id(doc.Id, doc.Routing)); } // fallback to doing a find if (itemsToFind.Count > 0 && (HasParent || ElasticIndex.HasMultipleIndexes)) { var response = await FindAsync(q => q.Id(itemsToFind.Select(id => id.Value)), o => o.PageLimit(1000)).AnyContext(); do { if (response.Hits.Count > 0) { hits.AddRange(response.Hits.Where(h => h.Document != null)); } } while (await response.NextPageAsync().AnyContext()); } if (IsCacheEnabled && options.ShouldUseCache()) { await AddDocumentsToCacheAsync(hits, options).AnyContext(); } return(hits.Where(h => h.Document != null && ShouldReturnDocument(h.Document, options)).Select(h => h.Document).ToList().AsReadOnly()); }