1

I have a table, let's call it Widgets, a Tags table with about 30 tags, a WidgetsTags table that joins each widget with any number of tags, and a table called LandingPages, the landing pages are for SEO purposes, they offer pre-filtered versions of the widgets table that match popular searches. That way when someone searches "Vehicle widgets for sale in Florida", in which matching tag logic would look like this:

For-Sale && Florida && (Car || Motorcycle || Truck)

There can be other forms of boolean logic for the various landing pages.

What I want to do is, when a user adds a widget to my app, and selects a handful of tags, the app then knows which landing pages to assign that widget to, based on each landing page's tag logic. I'm debating storing an actual boolean expression as a varchar in the landing page, then parsing each when a widget is added. Or some sort of system of tables, but I figured someone has wrestled with this problem before. If it helps, I am using C#, with a SQL Server backend.

  • Could you paraphrase the last paragraph? It's not clear enough. I've read it several times and kinda don't get it. In paragraph 1 you say langinpages are "pre-filtered versions of the widgets table" and then later you say that you assign langing pages to widgets... It's not clear what the relationship between widgets are landing pages is or what landing pages are. – Tulains Córdova Mar 20 '17 at 22:20
  • @TulainsCórdova the Landing Pages are like widget search pages with pre-filled in filter criteria, the purpose is so that they get indexed by search engines so they match popular searches. In the example given, "For-Sale","Florida","Car","Motorcycle","Truck" are all tags that can be applied to a widget. Given the boolean expression of that page, any widget that has the For-Sale tag, AND the Florida tag, AND at least one of (Car,Motorcycle,Truck) would get assigned to that page. – Neil N Mar 21 '17 at 15:32
0

I decided to use a varchar field on the LandingPages table to store a boolean expression. Then when a widget is added, the list of LandingPages gets loaded, then the boolean expression is run against the tags for that widget, the ones that return true get that widget associated with them.

Goes something like this:

var evaluator = new ExpressionEvaluator();
evaluator.Tags = widget.Tags;  // List<string>

foreach(var page in LandginPages)
{
    if(evaluator.Evaluate(page.filterExpression))
    {
        // Create widget <-> LandingPage association here
    }
}

The expression evaluator class I created:

public class ExpressionEvaluator
{
    public List<string> Tags = new List<string>();

    public bool Evaluate(string exp)
    {
        // Split on first space
        var tokens = exp.Split(new char[] { ' ' }, 3, StringSplitOptions.RemoveEmptyEntries);

        // If just one or none, eval the tag
        if (tokens.Length < 2)
        {
            return Tags.Contains(exp);
        }

        // Pull out the left, op, right
        var left = tokens[0];
        var op = tokens[1];
        var right = tokens[2];

        switch (op)
        {
            case "&&":
                return AND(left, right);
                break;
            case "||":
                return OR(left, right);
                break;
        }

        return false;
    }

    private bool AND(string left, string right)
    {
        // Short circuit on the left
        if (!Tags.Contains(left))
        {
            return false;
        }

        return Evaluate(right);
    }

    private bool OR(string left, string right)
    {
        // Short circuit on the left
        if(Tags.Contains(left))
        {
            return true;
        }

        return Evaluate(right);
    }
}

To see all the tests I wrote to create this class, check out the repo on GitHub: https://github.com/NNordhaus/ExpressionEvaluator

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.