I have an entity Card
with a property Title
. I also have a field for searching through all the cards' titles with a search term. Let's say that I have card titles 'Dark Magician' and 'Blue Eyed Dragon'. If I search for 'Magician Dragon' I need to receive both the cards, if I search for 'Blue dog with a house' I need to receive the 'Blue Eyed Dragon'card.
As of now I have this code, but I can't make up the correct LINQ code.
CardsController.cs, the All view:
public IActionResult All(string searchTerm)
{
var cardsQuery = this.data.Cards.AsQueryable();
if (!string.IsNullOrWhiteSpace(searchTerm))
{
//Removing all the white spaces and then joining the different words by a space
searchTerm = string.Join(" ", searchTerm.Split(default(string[]), StringSplitOptions.RemoveEmptyEntries));
//Splitting the searchTerm and making it a list of strings
var searchTermSplitted = searchTerm.Split().ToList();
//Trying to check if any and which words are contained in any of the cards' titles
cardsQuery = cardsQuery
.Where(c => c.Title.ToLower().Contains(searchTermSplitted)); //Not working, just for the idea
}
var cards = cardsQuery
.OrderByDescending(c => c.Id)
.Select(c => new CardListingViewModel
{
Title = c.Title,
ImageUrl = c.ImageUrl,
Category = c.Category.Name,
Condition = c.Condition.Name
})
.ToList();
return View(new AllCardsQueryModel
{
Cards = cards
}); ;
}
CodePudding user response:
Try following :
List<Card> cards = new List<Card>();
string searchPattern = "Magician Dragon";
List<string> searchWords = searchPattern.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).ToList();
var results = cards.Where(x => searchWords.Any(y => x.Title.Contains(y)));
CodePudding user response:
So having a search phrase like
Blue dog with a house
we shoud return all the items which share at least one word with the search phrase.
If data.Cards
is not that large and we can use AsEnumerable()
in order to filter on client:
string searchTerm = "Blue dog with a house";
var wordsToFind = new HashSet<string>(
searchTerm.Split(' ', StringSplitOptions.RemoveEmptyEntries),
StringComparer.OrdinalIgnoreCase);
var result = data
.Cards
.AsEnumerable() // we will sort on the client
.Where(card => card
.Title
.Split(' ')
.Any(word => words.Contains(word)))
.Select(c => new CardListingViewModel() {
Title = c.Title,
ImageUrl = c.ImageUrl,
Category = c.Category.Name,
Condition = c.Condition.Name
})
.ToList();