private IQueryable <Activity> GetActivityQuery(FindParams findParams, Data.Shared.Models.User user, int?specimenId = null) { var activityQuery = _activityRepository.WhereWithIncludes(a => (!specimenId.HasValue || a.SpecimenId == specimenId) && (!findParams.ContactsOnly || a.User.Contacts.Any(u => u.ContactUserId == user.Id)) && (findParams.SearchTextQuery == null || EF.Functions.Like(a.Name, findParams.SearchTextQuery) || EF.Functions.Like(a.Specimen.InventoryItem.Name, findParams.SearchTextQuery) || (a.Specimen.Lifeform != null && EF.Functions.Like(a.Specimen.Lifeform.CommonName, findParams.SearchTextQuery)) || (a.Specimen.Lifeform != null && EF.Functions.Like(a.Specimen.Lifeform.ScientificName, findParams.SearchTextQuery))), false, a => a.Include(a => a.Specimen) .Include(a => a.Specimen.InventoryItem) .Include(a => a.Specimen.Lifeform) .Include(a => a.User)); activityQuery = activityQuery.CanViewContent(user); if (!findParams.ContactsOnly && !string.IsNullOrEmpty(findParams.CreatedBy)) { activityQuery = activityQuery.Where(a => a.CreatedBy == findParams.CreatedBy); } activityQuery = OrderBy(activityQuery, findParams.SortBy, findParams.SortDirection); return(activityQuery); }
public async Task <Data.Shared.Models.User> GetUserContactStatusAsync(Data.Shared.Models.User requestor, Data.Shared.Models.User user) { var userContact = await _userContactRepository.Where(uc => uc.UserId == user.Id && uc.ContactUserId == requestor.Id) .FirstOrDefaultAsync(); if (userContact != null) { user.Contacts = new List <Data.Shared.Models.UserContact> { userContact.AsModel() }; } else { var userContactRequest = await _userContactRequestRepository.Where(uc => uc.UserId == user.Id && uc.ContactUserId == requestor.Id) .FirstOrDefaultAsync(); if (userContactRequest != null) { user.ContactRequests = new List <Data.Shared.Models.UserContactRequest> { userContactRequest.AsModel() }; } } return(user); }
public async Task <Data.Shared.Models.Origin> GetOriginAsync(int id, Data.Shared.Models.User user) { var originQuery = _originRepository.WhereWithIncludes(o => o.Id == id, false, o => o.Include(o => o.ParentOrigin) .Include(o => o.Location) .Include(o => o.User) .Include(o => o.User.Photo)); originQuery = originQuery.CanViewContent(user); var origin = await originQuery.FirstOrDefaultAsync(); return(origin?.AsModel()); }
public async Task <Data.Shared.Models.Activity> GetActivityAsync(int id, Data.Shared.Models.User user) { var activityQuery = _activityRepository.WhereWithIncludes(a => a.Id == id, false, a => a.Include(a => a.Specimen) .Include(a => a.Specimen.InventoryItem) .Include(a => a.Specimen.Lifeform) .Include(a => a.User) .Include(a => a.User.Photo)); activityQuery = activityQuery.CanViewContent(user); var activity = await activityQuery.FirstOrDefaultAsync(); return(activity?.AsModel()); }
public async Task <Data.Shared.Models.PlantInfo> GetPlantInfoAsync(int id, Data.Shared.Models.User user) { var plantInfoQuery = _plantInfoRepository.WhereWithIncludes(p => p.Id == id, false, p => p.Include(p => p.Lifeform) .Include(p => p.Taxon) .Include(p => p.Origin) .Include(p => p.User) .Include(p => p.User.Photo) .Include(p => p.MinimumZone) .Include(p => p.MaximumZone)); plantInfoQuery = plantInfoQuery.CanViewContent(user); var plantInfo = await plantInfoQuery.FirstOrDefaultAsync(); var plantLocations = await _plantLocationRepository.WhereWithIncludes(pl => pl.PlantInfoId == plantInfo.Id, false, pl => pl.Include(pl => pl.Location)).GetAllAsync(); plantInfo.PlantLocations = plantLocations; return(plantInfo?.AsModel()); }
public async Task <SearchResponse <Specimen> > SearchAsync(FindParams <Data.Shared.Models.Specimen> findParams, Data.Shared.Models.User user) { var specimenFindParams = findParams as SpecimenFindParams; var searchTerm = findParams.SearchText; var musts = GetFilters(findParams); var shoulds = new List <QueryContainer>(); var query = new QueryContainerDescriptor <Specimen>(); if (!string.IsNullOrEmpty(searchTerm)) { var fields = new FieldsDescriptor <Specimen>(); fields = fields.Field(f => f.Name) .Field(f => f.Lifeform.CommonName) .Field(f => f.Lifeform.ScientificName); if (findParams.UseNGrams) { fields = fields.Field("name.nameSearch"); } shoulds.Add(query.MultiMatch(mm => mm.Fields(mmf => fields) .Query(searchTerm) .Fuzziness(Fuzziness.AutoLength(1, 5)))); } musts.Add(FilterByVisibility(query, user)); var searchDescriptor = new SearchDescriptor <Specimen>() .Query(q => q .Bool(b => b .Should(shoulds.ToArray()) .Must(musts.ToArray()).MinimumShouldMatch(string.IsNullOrEmpty(searchTerm) ? 0 : 1))); var countDescriptor = new CountDescriptor <Specimen>() .Query(q => q .Bool(b => b .Should(shoulds.ToArray()) .Must(musts.ToArray()).MinimumShouldMatch(string.IsNullOrEmpty(searchTerm) ? 0 : 1))); // Sort var specimenSorts = GetSpecimenSorts(); if (!string.IsNullOrEmpty(findParams.SortBy)) { if (findParams.SortDirection == SortDirection.Ascending) { searchDescriptor.Sort(s => s.Field(f => f.Field(specimenSorts[findParams.SortBy]).Ascending())); } else { searchDescriptor.Sort(s => s.Field(f => f.Field(specimenSorts[findParams.SortBy]).Descending())); } } else if (string.IsNullOrEmpty(findParams.SearchText)) { searchDescriptor.Sort(s => s.Field(f => f.Field(specimenSorts["DateModified"]).Descending()).Field(f => f.Field(specimenSorts["DateCreated"]).Descending())); } var aggregations = new AggregationContainerDescriptor <Specimen>(); var searchFilters = new List <SearchFilter <Specimen> > { new SearchValueFilter <Specimen, string>("Stage", "specimenStage", specimenFindParams.Filters.StageFilter.Value) }; foreach (var filter in searchFilters) { if (filter is NestedSearchValueFilter <Specimen, string> nestedFilter) { aggregations = nestedFilter.ToAggregationContainerDescriptor(aggregations); } else if (filter is SearchRangeFilter <Specimen, double> searchRangeFilter) { aggregations = searchRangeFilter.ToAggregationContainerDescriptor(aggregations); } else if (filter is SearchValueFilter <Specimen, string> searchValueFilter) { aggregations = searchValueFilter.ToAggregationContainerDescriptor(aggregations); } } searchDescriptor.Aggregations(a => aggregations); var response = await _searchClient.SearchAsync(pi => searchDescriptor.Skip(findParams.Skip).Take(findParams.Take), pi => countDescriptor); response.AggregationResult = ProcessAggregations(response, specimenFindParams); return(response); }
private QueryContainer FilterByVisibility(QueryContainerDescriptor <Specimen> query, Data.Shared.Models.User user) => query.Bool(b => b .Should(s => !s.Exists(t => t.Field(f => f.InventoryItem.User)) || s.Term(t => t.InventoryItem.Visibility, Visibility.Public) || s.Term(t => t.InventoryItem.User.Id, user.Id) || // Not hidden (!(s.Term(t => t.InventoryItem.Visibility, Visibility.Hidden) || (s.Term(t => t.InventoryItem.Visibility, Visibility.Inherit) && s.Term(t => t.InventoryItem.User.PlantInfoVisibility, Visibility.Hidden)) || (s.Term(t => t.InventoryItem.User.PlantInfoVisibility, Visibility.Inherit) && s.Term(t => t.InventoryItem.User.ProfileVisibility, Visibility.Hidden))) && // Inherited ((s.Term(t => t.InventoryItem.Visibility, Visibility.Inherit) && (s.Term(t => t.InventoryItem.User.PlantInfoVisibility, Visibility.Public) || (s.Term(t => t.InventoryItem.User.PlantInfoVisibility, Visibility.Inherit) && s.Term(t => t.InventoryItem.User.ProfileVisibility, Visibility.Public)) || (s.Term(t => t.InventoryItem.User.PlantInfoVisibility, Visibility.Contacts) && s.Term(t => t.InventoryItem.User.ContactIds, user.Id)))) || // Contacts (s.Term(t => t.InventoryItem.Visibility, Visibility.Contacts) && s.Term(t => t.InventoryItem.User.ContactIds, user.Id))))));
public async Task <SearchResponse <PlantInfo> > SearchAsync(FindParams <Data.Shared.Models.PlantInfo> findParams, Data.Shared.Models.User user) { var plantInfoFindParams = findParams as PlantInfoFindParams; var searchTerm = findParams.SearchText; var shoulds = new List <QueryContainer>(); var query = new QueryContainerDescriptor <PlantInfo>(); if (!string.IsNullOrEmpty(searchTerm)) { var fields = new FieldsDescriptor <PlantInfo>(); fields = fields.Field(m => m.CommonName) .Field(m => m.ScientificName) .Field(m => m.Lifeform.CommonName) .Field(m => m.Lifeform.ScientificName) .Field("commonName.nameSearch") .Field("scientificName.nameSearch") .Field("lifeform.commonName.nameSearch") .Field("lifeform.scientificName.nameSearch"); shoulds.Add(query.MultiMatch(mm => mm.Fields(mmf => fields) .Query(searchTerm) .Fuzziness(Fuzziness.AutoLength(3, 5)))); shoulds.Add(query.Nested(n => n .Path(p => p.Synonyms) .Query(q => q .Match(sq => sq .Field("synonyms.name") .Query(searchTerm) .Fuzziness(Fuzziness.AutoLength(3, 5)))))); } var filters = plantInfoFindParams.Filters; var searchFilters = new List <SearchFilter <PlantInfo> > { new NestedSearchValueFilter <PlantInfo, string>(filters.RegionFilter.Name, "location.region.keyword", "plantLocations", filters.RegionFilter.Value), new SearchValuesFilter <PlantInfo, string>(filters.WaterFilter.Name, "waterTypes", filters.WaterFilter.MinimumValue, filters.WaterFilter.MaximumValue), new SearchValuesFilter <PlantInfo, string>(filters.LightFilter.Name, "lightTypes", filters.LightFilter.MinimumValue, filters.LightFilter.MaximumValue), new SearchValuesFilter <PlantInfo, string>(filters.BloomFilter.Name, "bloomTimes", filters.BloomFilter.MinimumValue?.ToString(), filters.BloomFilter.MaximumValue?.ToString()), new NestedSearchValueFilter <PlantInfo, string>(filters.ZoneFilter.Name, "id", "zones", filters.ZoneFilter.Value?.ToString()), new SearchRangeFilter <PlantInfo, double>(filters.HeightFilter.Name, "minHeight", "maxHeight", filters.HeightFilter.Values, filters.HeightFilter.Value, filters.HeightFilter.MaximumValue), new SearchRangeFilter <PlantInfo, double>(filters.SpreadFilter.Name, "minSpread", "maxSpread", filters.SpreadFilter.Values, filters.SpreadFilter.Value, filters.SpreadFilter.MaximumValue), new NestedSearchMultiValueFilter <PlantInfo, string, LocationStatus>(filters.NativeFilter.Name, "location.stateOrProvince.keyword", "plantLocations", "status", filters.NativeFilter.Value, filters.NativeFilter.Status) }; var musts = GetFilters(plantInfoFindParams, searchFilters); musts.Add(FilterByVisibility(query, user)); if (plantInfoFindParams.Lifeform != null) { musts.Add(query.Bool(b => b.Must(m => m.Term(t => t.Lifeform.Id, plantInfoFindParams.Lifeform.LifeformId)))); } var searchDescriptor = new SearchDescriptor <PlantInfo>() .Query(q => q .Bool(b => b .Should(shoulds.ToArray()) .Must(musts.ToArray()).MinimumShouldMatch(string.IsNullOrEmpty(searchTerm) ? 0 : 1))); var countDescriptor = new CountDescriptor <PlantInfo>() .Query(q => q .Bool(b => b .Should(shoulds.ToArray()) .Must(musts.ToArray()).MinimumShouldMatch(string.IsNullOrEmpty(searchTerm) ? 0 : 1))); var aggregations = new AggregationContainerDescriptor <PlantInfo>(); foreach (var filter in searchFilters) { if (filter is NestedSearchMultiValueFilter <PlantInfo, string, LocationStatus> nestedMultiFilter) { aggregations = nestedMultiFilter.ToAggregationContainerDescriptor(aggregations); } else if (filter is NestedSearchValueFilter <PlantInfo, string> nestedFilter) { aggregations = nestedFilter.ToAggregationContainerDescriptor(aggregations); } else if (filter is SearchRangeFilter <PlantInfo, double> searchRangeFilter) { aggregations = searchRangeFilter.ToAggregationContainerDescriptor(aggregations); } else if (filter is SearchValuesFilter <PlantInfo, string> searchValuesFilter) { aggregations = searchValuesFilter.ToAggregationContainerDescriptor(aggregations); } else if (filter is SearchValueFilter <PlantInfo, string> searchValueFilter) { aggregations = searchValueFilter.ToAggregationContainerDescriptor(aggregations); } } searchDescriptor.Aggregations(a => aggregations); // Sort var plantInfoSorts = GetPlantInfoSorts(); if (!string.IsNullOrEmpty(findParams.SortBy)) { if (findParams.SortDirection == SortDirection.Ascending) { searchDescriptor.Sort(s => s.Field(f => f.Field(plantInfoSorts[findParams.SortBy]).Ascending())); } else { searchDescriptor.Sort(s => s.Field(f => f.Field(plantInfoSorts[findParams.SortBy]).Descending())); } } else if (string.IsNullOrEmpty(findParams.SearchText)) { searchDescriptor.Sort(s => s.Field(f => f.Field(plantInfoSorts["DateModified"]).Descending()).Field(f => f.Field(plantInfoSorts["DateCreated"]).Descending())); } var response = await _searchClient.SearchAsync(pi => searchDescriptor.Skip(findParams.Skip).Take(findParams.Take), pi => countDescriptor); response.AggregationResult = ProcessAggregations(response, plantInfoFindParams); return(response); }
public async Task <SearchResponse <Lifeform> > SearchAsync(FindParams <Data.Shared.Models.Lifeform> findParams, Data.Shared.Models.User user) { var searchTerm = findParams.SearchText; var shoulds = new List <QueryContainer>(); var query = new QueryContainerDescriptor <PlantInfo>(); if (!string.IsNullOrEmpty(searchTerm)) { shoulds.Add(query.MultiMatch(mm => mm.Fields(mmf => mmf .Field(m => m.CommonName) .Field(m => m.ScientificName) .Field(m => m.Lifeform.CommonName) .Field(m => m.Lifeform.ScientificName) .Field("commonName.nameSearch") .Field("scientificName.nameSearch") .Field("lifeform.commonName.nameSearch") .Field("lifeform.scientificName.nameSearch")) .Query(searchTerm))); shoulds.Add(query.Nested(n => n .Path(p => p.Synonyms) .Query(q => q .Match(sq => sq .Field("synonyms.name") .Query(searchTerm))))); } var searchDescriptor = new SearchDescriptor <PlantInfo>() .Source(s => s.Includes(i => i.Field(p => p.Lifeform))) .Query(q => q .Bool(b => b .Should(shoulds.ToArray()))); var countDescriptor = new CountDescriptor <PlantInfo>() .Query(q => q .Bool(b => b .Should(shoulds.ToArray()))); var response = await _searchClient.SearchAsync(pi => searchDescriptor.Skip(findParams.Skip).Take(findParams.Take), pi => countDescriptor); return(new SearchResponse <Lifeform> { Count = response.Count, Documents = response.Documents.Select(d => new Lifeform { Id = d.Lifeform.Id, CommonName = d.Lifeform.CommonName, ScientificName = d.Lifeform.ScientificName, }).ToList(), Aggregations = null }); }
public async Task <SpecimenFindResult> FindSpecimens(SpecimenFindParams findParams, Data.Shared.Models.User user) { if (findParams.Filters == null) { findParams.Filters = new SpecimenFilters(); } var specimenSearch = await _specimenIndex.SearchAsync(findParams, user); var specimenIds = specimenSearch.Documents.Select(p => p.Id).ToArray(); var specimenQuery = _specimenRepository.WhereWithIncludes(s => specimenIds.Contains(s.Id), false, s => s.Include(s => s.InventoryItem) .Include(s => s.InventoryItem.Inventory) .Include(s => s.InventoryItem.Origin) .Include(s => s.InventoryItem.User) .Include(s => s.Lifeform)); specimenQuery = specimenQuery.CanViewContent(user); var specimenResult = specimenQuery.GetSomeAsync(track: false); var specimens = new List <Data.Shared.Models.Specimen>(); await foreach (var specimen in specimenResult) { specimens.Add(specimen.AsModel()); } if (specimenSearch.Aggregations != null) { foreach (var aggregation in specimenSearch.AggregationResult) { if (aggregation.Name == "Stage") { var filter = findParams.Filters.StageFilter; var values = aggregation.Values; values = values.Prepend(new KeyValuePair <string, long?>("", null)).ToDictionary(k => k.Key, v => v.Value); filter.FacetValues = values; } } } if (specimenSearch.Aggregations != null) { foreach (var aggregation in specimenSearch.AggregationResult) { var filter = SpecimenFindParams.GetFilter(aggregation.Name, findParams); if (filter is SelectFilter <string> selectFilter) { var values = aggregation.Values; values = values.Prepend(new KeyValuePair <string, long?>("", null)).ToDictionary(k => k.Key, v => v.Value); selectFilter.FacetValues = values; } if (filter is SelectRangeFilter <double> selectRangeFilter) { var values = aggregation.Values.ToDictionary(k => double.Parse(k.Key), v => v.Value).OrderBy(k => k.Key).ToDictionary(k => k.Key, v => v.Value); if (aggregation.Name.Contains("Min")) { selectRangeFilter.MinFacetValues = values; } else { selectRangeFilter.MaxFacetValues = values; } } if (filter is RangeFilter <string> rangeFilter) { var values = aggregation.Values; values = values.Prepend(new KeyValuePair <string, long?>("", null)).ToDictionary(k => k.Key, v => v.Value); rangeFilter.FacetValues = values; } } } return(new SpecimenFindResult { Results = specimenIds.Join(specimens, sid => sid, s => s.SpecimenId, (id, s) => s).ToList(), Count = specimenSearch.Count, Filters = findParams.Filters }); }
public async Task <Data.Shared.Models.Specimen> GetSpecimenAsync(int specimenId, Data.Shared.Models.User user) { var specimenQuery = _specimenRepository.WhereWithIncludes(s => s.Id == specimenId, false, s => s.Include(s => s.InventoryItem) .Include(s => s.InventoryItem.Inventory) .Include(s => s.InventoryItem.Origin) .Include(s => s.Lifeform) .Include(s => s.InventoryItem.User) .Include(s => s.InventoryItem.User.Photo)); specimenQuery = specimenQuery.CanViewContent(user); var specimen = await specimenQuery.FirstOrDefaultAsync(); return(specimen?.AsModel()); }
public async Task <FindResult <Data.Shared.Models.Origin> > FindOrigins(FindParams findParams, Data.Shared.Models.User user) { var originQuery = _originRepository.WhereWithIncludes(o => findParams.SearchTextQuery == null || EF.Functions.Like(o.Name, findParams.SearchTextQuery) || EF.Functions.Like(o.Description, findParams.SearchTextQuery) || EF.Functions.Like(o.Location.City, findParams.SearchTextQuery) || EF.Functions.Like(o.Location.AddressLine1, findParams.SearchTextQuery) || EF.Functions.Like(o.Location.StateOrProvince, findParams.SearchTextQuery), false, o => o.Include(o => o.Location) .Include(o => o.User)); originQuery = originQuery.CanViewContent(user); if (!string.IsNullOrEmpty(findParams.CreatedBy)) { originQuery = originQuery.Where(s => s.CreatedBy == findParams.CreatedBy); } else { originQuery = originQuery.Where(s => s.CreatedBy != null); } originQuery = OrderBy(originQuery, findParams.SortBy, findParams.SortDirection); var count = originQuery.Count(); var originResult = originQuery.GetSomeAsync(skip: findParams.Skip, take: findParams.Take, track: false); var origins = new List <Data.Shared.Models.Origin>(); await foreach (var origin in originResult) { origins.Add(origin.AsModel()); } return(new FindResult <Data.Shared.Models.Origin> { Results = origins, Count = count }); }
public async Task <Data.Shared.Models.User> GetUserAsync(int id, Data.Shared.Models.User requestor) { var user = await _userRepository.GetWithIncludesAsync(u => u.Id == id, false, u => u.Include(u => u.Location)); return(user.AsModel()); }
public async Task <FindResult <Data.Shared.Models.Activity> > FindScheduledActivities(FindParams findParams, Data.Shared.Models.User user, DateTime date) { var activityQuery = GetActivityQuery(findParams, user); activityQuery = activityQuery.Where(a => a.DateScheduled >= date); return(await FindResult(activityQuery, findParams)); }
public async Task <FindResult <Data.Shared.Models.Activity> > FindActivities(FindParams findParams, Data.Shared.Models.User user, int?specimenId = null) { var activityQuery = GetActivityQuery(findParams, user, specimenId); return(await FindResult(activityQuery, findParams)); }
public async Task <PlantInfoFindResult> FindPlantInfos(PlantInfoFindParams findParams, Data.Shared.Models.User user) { if (findParams.Filters == null) { findParams.Filters = new PlantInfoFilters(); } var plantInfoSearch = await _plantInfoIndex.SearchAsync(findParams, user); var plantInfoIds = plantInfoSearch.Documents.Select(p => p.Id).ToArray(); var plantInfoQuery = _plantInfoRepository.WhereWithIncludes(p => plantInfoIds.Contains(p.Id), false, p => p.Include(p => p.Lifeform) .Include(p => p.Taxon) .Include(p => p.Origin) .Include(p => p.User) .Include(p => p.MinimumZone).Include(p => p.MaximumZone)); plantInfoQuery = plantInfoQuery.CanViewContent(user); var plantInfoResult = plantInfoQuery.GetSomeAsync(track: false); var plantInfos = new List <Data.Shared.Models.PlantInfo>(); await foreach (var plantInfo in plantInfoResult) { plantInfos.Add(plantInfo.AsModel()); } if (plantInfoSearch.Aggregations != null) { foreach (var aggregation in plantInfoSearch.AggregationResult) { var filter = PlantInfoFindParams.GetFilter(aggregation.Name, findParams); if (filter is SelectFilter <string> selectFilter) { var values = aggregation.Values; if (!values.Any(v => v.Key == "0")) { values = values.Prepend(new KeyValuePair <string, long?>("0", null)).ToDictionary(k => k.Key, v => v.Value); } selectFilter.FacetValues = values; } if (filter is SelectRangeFilter <double> selectRangeFilter) { var values = aggregation.Values.ToDictionary(k => double.Parse(k.Key), v => v.Value).OrderBy(k => k.Key).ToDictionary(k => k.Key, v => v.Value); if (aggregation.Name.Contains("Min")) { selectRangeFilter.MinFacetValues = values; } else { selectRangeFilter.MaxFacetValues = values; } } if (filter is RangeFilter <string> rangeFilter) { var values = aggregation.Values; if (aggregation.Name == "Bloom") { values = aggregation.Values.ToDictionary(k => int.Parse(k.Key), v => v.Value).OrderBy(k => k.Key).ToDictionary(k => k.Key.ToString(), v => v.Value); } if (!values.Any(v => v.Key == "0")) { values = values.Prepend(new KeyValuePair <string, long?>("0", null)).ToDictionary(k => k.Key, v => v.Value); } rangeFilter.FacetValues = values; } } } return(new PlantInfoFindResult { Count = plantInfoSearch.Count, Results = plantInfoIds.Join(plantInfos, pid => pid, pi => pi.PlantInfoId, (id, p) => p).ToList(), Filters = findParams.Filters }); }
public async Task <Data.Shared.Models.User> GetUserByNameAsync(string name, Data.Shared.Models.User requestor) { var user = await _userRepository.GetWithIncludesAsync(u => u.DisplayName == name, false, u => u.Include(u => u.Location)); return(user.AsModel()); }