Examiness hints and tips from the trenches part 11

As I have moved roles I have decided to start blogging again on my old wordpress blog. Those of you who are aware I have been blogging about Examine see the Cogworks blog.  In this post I am going to cover how to perform range searches.

I recently did this for a client. The scenario was that they had 100 products each tagged with a feature that was a multi tree node picker.  They have 6 features 5 of which were a range e.g weight this had values

0-300 gsm
301-600 gsm
601-1000 gsm
1001-2000 gsm
2000+gsm
Don’t Know

The home page of the site had a search form that allowed you to pick one range value for each of the features. This would then perform examine search and return products matched.

To implement range search I implemented GatheringNodeData event and injected in some massaged data for each of the ranges.  So for weight I did the following

int nodeId = int.Parse(e.Fields[field]); // get the node id for the feature eg weight
//the value is mntp lookup so get the node
 var node = ApplicationContext.Current.Services.ContentService.GetById(nodeId);

string fieldRaw = node.Name; //get the value

                if (fieldRaw.Contains("+"))
                {
                    int fieldValue = 0;
                    if (isMm)
                    {
                        decimal tmp = decimal.Parse(fieldRaw.Replace("+", ""))*10;
                        fieldValue = (int) tmp;
                    }
                    else
                    {
                        //only one value inject that and a fake max
                        fieldValue = int.Parse(fieldRaw.Replace("+", ""));
                    }

                    InjectRange(fieldValue.ToString("D6"), Helpers.Constants.Examine.MaxValue, e, field);
                }
                else
                {
                    //we have min and max so put both in
                    string[] values = fieldRaw.Split('-');
                    int valueMin = 0;
                    int valueMax = 0;

                    if (isMm)
                    {
                        valueMin = (int) (float.Parse(values[0]) * 10);
                        valueMax = (int) (float.Parse(values[1]) * 10);
                    }
                    else
                    {
                         valueMin = int.Parse(values[0]);
                         valueMax = int.Parse(values[1]);
                    }

                    InjectRange(valueMin.ToString("D6"), valueMax.ToString("D6"), e, field);
                }
            }

        }

        private void InjectRange(string min, string max, IndexingNodeDataEventArgs e, string field)
        {
            e.Fields.Add(Helpers.Constants.Examine.MinPrefix + field, min);
            e.Fields.Add(Helpers.Constants.Examine.MaxPrefix + field, max);
        }

This takes the value replaces any display content that is not needed e.g gsm and then splits on – this gives us the lower and upper values for the range.  I then inject into the index into 2 new fields a lower and upper value. The values for 0-300 in the index look like

min_weight 000000

max_weight 000300

If the value is for example a single positive like 2000+ gsm then I add the 2000 value and in the index the value looks like

min_weight 002000

max_weight 100000

The last number is a fake maximum this will come in handy when doing the range search. My dropdowns on the home page display values like 0-300gsm but contain actual values 000000-000300 when performing a search the code takes those drop down values to create a range query e.g.

            string[] values = query[key].Split('-');
            if (query[key].Contains(Constants.Examine.MaxValue))
            {
                //we are doing a + max value so only need one value for the range
                examineQuery.And().Range(Constants.Examine.MaxPrefix + key, values[1], Constants.Examine.MaxValue);           
            }
            else
            {
                if (key == "MinTemp")
                {
                    /*these are negative so swap them around*/
                    examineQuery.And().Range(Constants.Examine.MinPrefix + key, values[0], Constants.Examine.MaxValue);
                    examineQuery.And().Range(Constants.Examine.MaxPrefix + key, values[1], Constants.Examine.MaxValue);
                }
                else
                {
                    examineQuery.And().Range(Constants.Examine.MinPrefix + key, Constants.Examine.MinValue, values[0]);
                    examineQuery.And().Range(Constants.Examine.MaxPrefix + key, Constants.Examine.MinValue, values[1]);
                }
            }
Advertisements