MongoDB substring product search order by highest

2020-07-28 11:18发布

问题:

I'm not so good in Mongodb. That's my first project using this. I'm working on some sort of shop website. We're using C# and newest C# driver for mongodb. I need an idea how to implement my algorithm to filter products based on user's input. Here's how my algorithm works/should work.

  1. User type something like "Blue adidas men spiderman cotton t-shirt"
  2. I split whole phrase into single words so I have "blue", "adidas", "men", "spiderman", "cotton", "t-shirt"
  3. I check each word against retailer, color, category names in my db. So here's how it goes.

    • "Blue" - oh, it's a color filter let's filter this against proper field in my mongodb document.
    • "adidas" - ok, it's retailer. Do the same as in point above
    • "men" - it's a category. Ok so let's search only in this category.
    • "cotton" - I don't filter by textile. Can't filter by this.
    • "spiderman" - definetly not a retailer, color etc. Can't filter using this.
    • "t-shirt" - Ok. It's category name that appears as child category for kids, men, women but since I already have "men" as my category I just go a little bit deeper into my category structure - Now I update my categoryId I want to filter against and it's t-shirt category under men category.

      1. Ok. I parsed few filter params from user input but I still have cotton and spiderman word. And that's where I'm lost.

I would like to not ignore this "spiderman" and "cotton" words. I would like to actually get ALL items from database order by word coverage in its product name so my expected result (ofc with all retailer, color etc filters applied first) are:

products that names contain both "spiderman" and "cotton" products products that names contain either "spiderman" or "cotton"

How can I do that?

回答1:

First of all, you can combine multiple filters with using & operator like this:

var builder = Builders<Product>.Filter;
FilterDefinition<Product> filter = builder.Empty;
filter &= builder.Eq("Color", "blue");
filter &= builder.Eq("Retailer", "adidas");
filter &= builder.Eq("Category", "men");

Then, you can use Regex to filter the products the names of which contain any rest words/all rest words.
OR search (the name contains "cotton" OR "spiderman")

var restWords = new string[] { "cotton", "spiderman" };
var orReg = new System.Text.RegularExpressions.Regex(string.Join("|", restWords));
filter &= builder.Regex("Name", BsonRegularExpression.Create(orReg));

List<Product> filteredList = products.Find(filter).ToListAsync().Result;

AND search (the name contains "cotton" AND "spiderman")

foreach (var word in restWords)
{
    filter &= builder.Regex("Name", BsonRegularExpression.Create(new System.Text.RegularExpressions.Regex(word)));
}

List<Product> filteredList = products.Find(filter).ToListAsync().Result;