public async Task SearchForRecipesByIngrediantFuzzy() { using (var client = await this.CreateExternalClient()) { var recipe = await client.GetRecipes(entriesPerPage : Int32.MaxValue); var firstRecipe = recipe.Entries.First(); var ingrediants = await client.GetRecipeIngrediantsAsync(firstRecipe.Id); var searchModel = new RecipeSearchViewModel() { Ingrediants = new List <string>() { ingrediants.First().Name + "ABC" } }; var result = await client.GetRecipes(searchModel); Assert.NotNull(result); Assert.NotNull(result.Entries); Assert.NotEmpty(result.Entries); Assert.True(result.Entries.Any(x => x.Id.Equals(firstRecipe.Id))); } }
public async Task <IActionResult> Search(string searchInfo, string searchType) { var pageNumber = 1; var model = new RecipeSearchViewModel(); model.Recipes = new List <Result>(); if (!String.IsNullOrEmpty(searchInfo)) { if (searchType == "AllRecipes") { do { var response = await _RecipeClient.GetAllRecipes(pageNumber); foreach (var recipe in response.results) { if (recipe.title.Contains(searchInfo, StringComparison.OrdinalIgnoreCase)) { model.Recipes.Add(recipe); } } pageNumber = pageNumber + 1; }while (pageNumber < 100); } } return(View(model)); }
public async Task SearchForRecipesByName() { using (var client = await this.CreateExternalClient()) { var allRecipe = await client.GetRecipes(); var searchModel = new RecipeSearchViewModel() { Name = allRecipe.Entries.First().Name }; var result = await client.GetRecipes(searchModel); Assert.NotNull(result); Assert.NotNull(result.Entries); Assert.NotEmpty(result.Entries); Assert.Equal(1, result.Entries.Count()); var firstResult = result.Entries.First(); var compareRecipe = result.Entries.First(); Assert.Equal(compareRecipe.Name, firstResult.Name); Assert.Equal(compareRecipe.Creator, firstResult.Creator); Assert.Equal(compareRecipe.Id, firstResult.Id); } }
public async Task <IQueryable <ShortRecipeViewModel> > SearchForRecipes(RecipeSearchViewModel searchModel) { IQueryable <ShortRecipeViewModel> result = null; try { var recipes = this.Repository .GetAll() .Include(x => x.Images) .Include(x => x.Tags) .ThenInclude(x => x.RecipeTag); var searchresult = await this.SearchForRecipes(recipes, searchModel); result = searchresult .OrderByDescending(x => x.CookedCounter) .ThenByDescending(x => x.LastTimeCooked) .ProjectTo <ShortRecipeViewModel>(this.Mapper.ConfigurationProvider); this.Logger.LogDebug(new EventId(), $"Returned all recipes"); } catch (Exception e) { this.Logger.LogError(new EventId(), e, $"Error on receiving all recipes"); throw new Exception($"Error on receiving all recipes"); } return(result); }
private RecipeSearchViewModel CreateSearchModel(LuisResult result) { EntityRecommendation recipeName; if (!result.TryFindEntity(Entity_Recipename, out recipeName)) { recipeName = new EntityRecommendation(type: Entity_Recipename) { Entity = "" }; } IList <EntityRecommendation> ingrediants; if (!result.TryFindEntity(Entity_Ingrediant, out ingrediants)) { ingrediants = new List <EntityRecommendation>(); } IList <EntityRecommendation> tags; if (!result.TryFindEntity(Entity_Tag, out tags)) { tags = new List <EntityRecommendation>(); } var searchModel = new RecipeSearchViewModel() { Tags = tags.Where(x => !String.IsNullOrWhiteSpace(x.Entity)).Select(x => x.Entity.Replace(" ", "")).ToList(), Ingrediants = ingrediants.Where(x => !String.IsNullOrWhiteSpace(x.Entity)).Select(x => x.Entity.Replace(" ", "")).ToList(), Name = recipeName.Entity }; return(searchModel); }
public async Task <ListViewModel <ShortRecipeViewModel> > GetRecipes(RecipeSearchViewModel searchModel, int page = 0, int entriesPerPage = 5) { await this.SetBearerTokenAsync(HttpContext.Current); var newUrl = new Uri(this._client.BaseAddress, "Recipes/"); var query = $"?{nameof(page)}={page}&{nameof(entriesPerPage)}={entriesPerPage}"; if (searchModel != null) { query += $"&{this._client.ConvertToQueryString(searchModel)}"; } return(await this._client.GetAsync <ListViewModel <ShortRecipeViewModel> >(new Uri(newUrl, query).ToString())); }
public async Task <IActionResult> RecipeIndexResult(RecipeSearchViewModel model) { var response = await _recipeClient.GetAllRecipes(model.ingredient, model.title, model.page); var viewModel = new RecipeIndexViewModel(); viewModel.results = response.results .Select(response => new ResultsViewModel() { title = response.title, href = response.href, thumbnail = response.thumbnail }) .ToList(); return(View(viewModel)); }
public async Task <ListViewModel <ShortRecipeViewModel> > GetRecipes(RecipeSearchViewModel searchModel = null, int page = 0, int entriesPerPage = 10) { var newUrl = new Uri(this.Client.BaseAddress, "Recipes/"); var query = ""; if (searchModel != null) { var searchQuery = this.Client.ConvertToQueryString(searchModel); if (!String.IsNullOrWhiteSpace(searchQuery)) { query = $"?{searchQuery}"; } } query = QueryHelpers.AddQueryString(query, nameof(page), page.ToString()); query = QueryHelpers.AddQueryString(query, nameof(entriesPerPage), entriesPerPage.ToString()); return(await this.Client.GetAsync <ListViewModel <ShortRecipeViewModel> >(new Uri(newUrl, query).ToString())); }
public async Task SearchForRecipesByName() { await InitializeAsync(); using (var service = GetService()) { var firstRecipe = await this.DbContext.Recipes.FirstAsync(); var searchModel = new RecipeSearchViewModel() { Name = firstRecipe.Name }; var output = await(await service.SearchForRecipes(searchModel)).ToListAsync(); Assert.NotNull(output); Assert.NotEmpty(output); Assert.Equal(1, output.Count); } }
// GET: Recipes public ActionResult Index(RecipeSearchViewModel model) { var recipes = db.Recipes.Include(r => r.Chef).Include(r => r.Country); if (model?.Continent_Id != null) { recipes = recipes.Where(R => R.Country.Continent_Id == model.Continent_Id); } if (model?.Country_Id != null) { recipes = recipes.Where(R => R.Country_Id == model.Country_Id); } if (!string.IsNullOrWhiteSpace(model.Search_KeyWord)) { recipes = recipes.Where(R => R.Dish_Description.Contains(model.Search_KeyWord) || R.Ingredients.Contains(model.Search_KeyWord) || R.Directions.Contains(model.Search_KeyWord)); } return(View(recipes.ToList())); }
public async Task <IActionResult> Index(int pageNumber) { var model = new RecipeSearchViewModel(); model.Recipes = new List <Result>(); var response = await _RecipeClient.GetAllRecipes(pageNumber); foreach (var recipe in response.results) { model.Recipes.Add(recipe); } model.currentPageNumber = pageNumber; model.nextPageNumber = pageNumber + 1; model.previousPageNumber = pageNumber - 1; return(View(model)); }
public async Task SearchForRecipesByTag() { await InitializeAsync(); using (var service = GetService()) { var tagWith = this.DbContext.RecipeTags.Include(x => x.Recipes).First(x => x.Recipes.Any()); var searchModel = new RecipeSearchViewModel() { Tags = new List <string>() { tagWith.Name } }; var output = await(await service.SearchForRecipes(searchModel)).ToListAsync(); Assert.NotNull(output); Assert.NotEmpty(output); Assert.Equal(tagWith.Recipes.Count, output.Count); } }
public async Task SearchForRecipesByTagFuzzy() { using (var client = await this.CreateExternalClient()) { var recipe = await client.GetRecipes(); var firstTagRecipe = recipe.Entries.First(x => x.Tags.Any()); var searchModel = new RecipeSearchViewModel() { Tags = new List <string>() { firstTagRecipe.Tags.First() + "ABC" } }; var result = await client.GetRecipes(searchModel); Assert.NotNull(result); Assert.NotNull(result.Entries); Assert.NotEmpty(result.Entries); Assert.True(result.Entries.Any(x => x.Id.Equals(firstTagRecipe.Id))); } }
public async Task SearchForRecipesByIngrediantWithDirectName() { using (var client = await this.CreateExternalClient()) { var ingrediantName = "salat"; var searchModel = new RecipeSearchViewModel() { Ingrediants = new List <string>() { ingrediantName } }; var result = await client.GetRecipes(searchModel); Assert.NotNull(result); Assert.NotNull(result.Entries); Assert.NotEmpty(result.Entries); var ingrediants = await client.GetRecipeIngrediantsAsync(result.Entries.First().Id); Assert.True(ingrediants.Any(x => x.Name.Equals(ingrediantName, StringComparison.CurrentCultureIgnoreCase))); } }
public async Task <ListViewModel <ShortRecipeViewModel> > GetRecipesAsync([FromQuery] RecipeSearchViewModel searchModel, [FromQuery] int page = 0, [FromQuery] int entriesPerPage = 10) { int recipeCount = 0; List <ShortRecipeViewModel> result = new List <ShortRecipeViewModel>(); try { IQueryable <ShortRecipeViewModel> entries = null; if (searchModel != null && searchModel.IsFilled()) { entries = await _service.SearchForRecipes(searchModel); } else { entries = _service.GetRecipes(); } recipeCount = await entries.CountAsync(); result = await entries .Skip(page *entriesPerPage) .Take(entriesPerPage) .ToListAsync(); foreach (var shortRecipeViewModel in result) { shortRecipeViewModel.Url = this.Url.RouteUrl("GetRecipeById", new { id = shortRecipeViewModel.Id }); } } catch (Exception e) { Console.WriteLine(e); throw; } return(new ListViewModel <ShortRecipeViewModel>(result, recipeCount, page + 1, entriesPerPage)); }
/// <summary> /// Initializes a new instance of the <see cref="ArticleListPage" /> class. /// </summary> public RecipeSearchPage() { InitializeComponent(); BindingContext = new RecipeSearchViewModel(Navigation); }
public PartialViewResult SearchRecipes(RecipeSearchViewModel vm) { return PartialView("_SearchRecipes", RecipeManager.SearchRecipes(vm.PageNumber, vm.PageSize, vm.SortType, vm.DataFilter)); }
public PartialViewResult SearchRecipes(RecipeSearchViewModel vm) { return(PartialView("_SearchRecipes", RecipeManager.SearchRecipes(vm.PageNumber, vm.PageSize, vm.SortType, vm.DataFilter))); }
public async Task <IActionResult> GetRecipesAsync([FromQuery] RecipeSearchViewModel searchModel, [FromQuery] int page = 0, [FromQuery] int entriesPerPage = 10) { await Client.SetBearerTokenAsync(this.HttpContext); return(Ok(await this.Client.GetRecipes(searchModel, page, entriesPerPage))); }
private async Task <IQueryable <Recipe> > SearchForRecipes(IQueryable <Recipe> recipes, RecipeSearchViewModel searchModel) { if (recipes == null) { throw new ArgumentNullException(nameof(recipes)); } if (searchModel == null) { return(recipes); } if (!String.IsNullOrWhiteSpace(searchModel.Name)) { recipes = recipes.Where(x => x != null && x.Name != null && x.Name.ToLower().Contains(searchModel.Name.ToLower())); } if (searchModel.Tags != null && searchModel.Tags.Any()) { var hits = await GetRecipesForTagSearchQuery(recipes.Include(x => x.Tags).ThenInclude(x => x.RecipeTag), searchModel); recipes = recipes.Where(x => x.Tags.Any(tag => hits.Contains(tag.RecipeTagId))); } if (searchModel.Ingrediants != null && searchModel.Ingrediants.Any()) { var hits = await GetRecipesForIngrediantsSearchQuery(recipes.Include(x => x.Ingrediants).ThenInclude(x => x.Ingrediant), searchModel); recipes = recipes.Where(x => x.Ingrediants.Any(ingrediant => hits.Contains(ingrediant.IngrediantId))); } return(recipes); }
private async Task <IEnumerable <int> > GetRecipesForTagSearchQuery(IIncludableQueryable <Recipe, RecipeTag> recipes, RecipeSearchViewModel model) { Dictionary <string, int> allEntries = null; var hits = new List <int>(); try { foreach (var searchModelTag in model.Tags) { // check if tag are found within database IEnumerable <int> currentHits = await recipes.SelectMany(x => x.Tags).Where(x => x.RecipeTag.Name.Contains(searchModelTag, true)).Select(x => x.RecipeTagId).ToListAsync(); if (currentHits.Any()) { hits.AddRange(currentHits); Logger.LogDebug($"Found fuzzy result in source data. Searched for {model}. Found {currentHits}"); continue; } // if no hits, lookup for fuzzy search cache for search query currentHits = await Repository.GetCachedFuzzyResultAsync(nameof(RecipeTag), searchModelTag); if (currentHits.Any()) { hits.AddRange(currentHits); Logger.LogDebug($"Found fuzzy result in cache data. Searched for {model}. Found {currentHits}"); continue; } // If no hits available, load all elements and process a fuzzy search on them // TODO: Change to 'real' caching (e.g. Lucene) if (allEntries == null) { // must be here to enable navigation property for RecipeTags var recipe = await recipes.FirstOrDefaultAsync(); allEntries = await recipes .SelectMany(x => x.Tags) .Select(x => x.RecipeTag) .Where(x => x != null) .Distinct() .ToDictionaryAsync(x => x.Name, x => x.Id); } var fuzzyHits = allEntries.Keys.Where(x => x.ApproximatelyEquals(searchModelTag, FuzzyStringComparisonTolerance.Normal, FuzzyStringComparisonOptions.UseLevenshteinDistance)).ToList(); if (!fuzzyHits.Any()) { Logger.LogDebug($"No result found for fuzzy search. Searched for {model}"); continue; } // if hit is found, save to cache for reuse foreach (var entry in fuzzyHits) { var newEntry = new FuzzyEntry() { Id = allEntries[entry], SearchQuery = searchModelTag, Type = nameof(RecipeTag) }; await Repository.SaveFuzzyEntryAsync(newEntry); hits.Add(allEntries[entry]); Logger.LogDebug($"Found data after calculating cache result. Searched for {model}. Found {entry} ({allEntries[entry]})"); } } } catch (Exception e) { Console.WriteLine(e); throw e; } return(hits.Distinct()); }
private async Task <IEnumerable <int> > GetRecipesForIngrediantsSearchQuery(IIncludableQueryable <Recipe, Ingrediant> recipes, RecipeSearchViewModel model) { Dictionary <string, int> allEntries = null; var hits = new List <int>(); try { foreach (var searchIngrediant in model.Ingrediants) { // check if tag are found within database IEnumerable <int> currentHits = await recipes .SelectMany(x => x.Ingrediants) .Where(ingrediant => ingrediant.Ingrediant.Name.Contains(searchIngrediant, true)) .Select(x => x.IngrediantId) .ToListAsync(); if (currentHits.Any()) { Logger.LogDebug($"Found fuzzy result in source data. Searched for {model}. Found {currentHits}"); hits.AddRange(currentHits); continue; } // if no hits, lookup for fuzzy search cache for search query currentHits = await Repository.GetCachedFuzzyResultAsync(nameof(Ingrediant), searchIngrediant); if (currentHits.Any()) { Logger.LogDebug($"Found fuzzy result in cache data. Searched for {model}. Found {currentHits}"); hits.AddRange(currentHits); continue; } // If no hits available, load all elements and process a fuzzy search on them // TODO: Change to 'real' caching (e.g. Lucene) if (allEntries == null) { var peng = await recipes.FirstOrDefaultAsync(); allEntries = await recipes .SelectMany(x => x.Ingrediants) .Select(x => x.Ingrediant) .Where(x => x != null) .Distinct() .ToDictionaryAsync(x => x.Name, x => x.Id); } var fuzzyoptions = new[] { FuzzyStringComparisonOptions.UseJaccardDistance, FuzzyStringComparisonOptions.UseLongestCommonSubstring, FuzzyStringComparisonOptions.UseSorensenDiceDistance }; var fuzzyHits = allEntries.Keys.Where(x => x.ApproximatelyEquals(searchIngrediant, FuzzyStringComparisonTolerance.Normal, fuzzyoptions)).ToList(); if (!fuzzyHits.Any()) { Logger.LogDebug($"No result found for fuzzy search. Searched for {model}"); continue; } // if hit is found, save to cache for reuse foreach (var entry in fuzzyHits) { var newEntry = new FuzzyEntry() { Id = allEntries[entry], SearchQuery = searchIngrediant, Type = nameof(Ingrediant) }; await Repository.SaveFuzzyEntryAsync(newEntry); hits.Add(allEntries[entry]); Logger.LogDebug($"Found data after calculating cache result. Searched for {model}. Found {entry} ({allEntries[entry]})"); } } } catch (Exception e) { this.Logger.LogError(new EventId(), e, $"Error on fuzzy search. Searched for {model}"); } return(hits.Distinct()); }