Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Mike Taylor 155 posts 353 karma points
    Aug 03, 2011 @ 11:36
    Mike Taylor
    0

    Using GroupedOr() to search one field for multiple terms?

    I'm trying to do something like this:

     

     

                var filter = criteria.Field("fieldA","fieldAValue")

                    .And()

                    .Field("fieldB","fieldBValue")

                    .And()

                    .GroupedOr( --- where fieldC contains any of a group of terms --- )

                    .Not()

                    .Field("umbracoNaviHide","1");

     

    So, the pseudo-logic is:

    (fieldA contains "fieldAValue") AND (fieldB contains "fieldBValue") AND ((fieldC contains "val1" OR fieldC contains "val2")) etc

    or

    +fieldA:fieldAValue +fieldB:fieldBValue +(fieldC:val1 fieldC:val2) -umbracoNaviHide:1

     

    Any ideas?

    Thanks,

    Mike

    +(subjectHierarchy:1079 subjectHierarchy:1081) +relatedLearningStages:1193 +relatedQualifications:1128 -parentNodeTypeAlias:Series

  • Arnold Visser 418 posts 778 karma points hq c-trib
    Aug 03, 2011 @ 11:45
    Arnold Visser
    0

    It's a combination of property configuring Examine and some code stuff.

    I use the code below to create a search for our uWebshop package in Examine:

    ExamineIndex.config:

    <IndexSet SetName="uWebshopIndexSet" IndexPath="~/App_Data/ExamineIndexes/uWebshop/">
    <IndexAttributeFields>
    <add Name="id" />
    <add Name="nodeName" />
    <add Name="path" />
    <add Name="nodeTypeAlias" />
    <add Name="parentID" />
    >
    <IndexUserFields/>
    <IncludeNodeTypes>
    <add Name="sswsProduct" />
    >
    <ExcludeNodeTypes />
    >

    ExamineSettings.config:

    <add name="uWebshopIndexer"
                 type="UmbracoExamine.LuceneExamineIndexer, UmbracoExamine"
                 dataService="UmbracoExamine.DataServices.UmbracoDataService, UmbracoExamine"
                 indexSet="uWebshopIndexSet"
                 supportUnpublished="false"
                 supportProtected="false"
                 runAsync="true"
                 interval="10"
    analyzer="Lucene.Net.Analysis.Standard.StandardAnalyzer, Lucene.Net"/>

    and

    <add name="uWebshopSearcher" type="UmbracoExamine.UmbracoExamineSearcher, UmbracoExamine"
               indexSet="uWebshopIndexSet" analyzer="Lucene.Net.Analysis.Standard.StandardAnalyzer, Lucene.Net"/>

    Razor script that takes the search value from a QueryString:


    @using System.Linq;
    @using System.Collections.Generic;
    @using SuperSimpleWebshop.Domain;
    @using SuperSimpleWebshop.XSLTExtensions;
    @using Examine;
    @using Examine.LuceneEngine.Providers;
    @using Examine.SearchCriteria;
    @using Examine.LuceneEngine.SearchCriteria;
    @using UmbracoExamine;
        

    @Get the search term from query string *@
    @{
      
                var SearchArray Request.QueryString["s"].Split(' ');
                
                var criteria ExamineManager.Instance
                        .SearchProviderCollection["uWebshopSearcher"]
                        .CreateSearchCriteria(IndexTypes.Content);

                
                Examine.SearchCriteria.IBooleanOperation filter null;
            
                int 0;
                for (0SearchArray.Lengthi++)
                {
                    if (filter == null)
                    {
                        filter criteria.GroupedOr(new string["title_NL""shortDescription_NL""longDescription_NL""tags_NL""productNumber" }SearchArray[i].MultipleCharacterWildcard());
                    }
                    else
                    {
                        filter filter.And().GroupedOr(new string["title_NL""shortDescription_NL""longDescription_NL""tags_NL""productNumber" }SearchArray[i].MultipleCharacterWildcard());
                    }
                }
      
                

                var SearchResultsCollection ExamineManager.Instance.SearchProviderCollection["uWebshopSearcher"].Search(filter.Compile());

      }  

     

    Furthermore I created an Examine event (this event fires when Examine indexes, NOT when you search) for working with comma separed values (for example when working with Tag fields), you just fill in the fields in a config file and your good to go:

    using Examine;
    using umbraco.BusinessLogic;
    using System.Xml;
    using System.Web;

    namespace
    SuperSimpleWesbhop.Examine.Examine_Classes
    {
        publicclassExamineEvents : ApplicationBase
        {
            public ExamineEvents()
            {
                Log.Add(LogTypes.Debug, 0, "ExamineEventsStart");
                var indexer = ExamineManager.Instance.IndexProviderCollection["uWebshopIndexer"];
                indexer.GatheringNodeData += GatheringNodeDataHandler;
            }
            void GatheringNodeDataHandler(object sender, IndexingNodeDataEventArgs e)
            {
                Log.Add(LogTypes.Debug, 0, "GatheringNodeDataHandler");
                XmlDocument xd = new XmlDocument();
                xd.Load(HttpContext.Current.Server.MapPath("/config/uWebshop/Examine.config"));
                foreach (XmlNode propertyAlias in xd.SelectNodes("Examine/propertyAlias"))
                {
                    var mntp = e.Fields[propertyAlias.InnerText];
                    Log.Add(LogTypes.Debug, 0, "examine MNTP before: " + mntp);
                    mntp = mntp.Replace(",", " ");
                    Log.Add(LogTypes.Debug, 0, "examine MNTP after: " + mntp);
                    e.Fields[propertyAlias.InnerText] = mntp;
                }
            }
        }
    }
  • Mike Taylor 155 posts 353 karma points
    Aug 03, 2011 @ 11:52
    Mike Taylor
    0

    Thanks Arnold.

    Am I right in thinking that instead of one call like this... (where 'values' is some kind of collection of search terms) 

    filter = filter.And().GroupedOr(new[] { "field" }, values);

    ...the solution is to loop through the search terms with multiple calls like this?

    foreach(string v in values)
    {
        filter = filter.And().GroupedOr(new[] { "field" }, v);

     

    This seems a bit counter-intuitive... it will call the And() on every iteration, surely?

    Cheers,

    Mike

  • Arnold Visser 418 posts 778 karma points hq c-trib
    Aug 03, 2011 @ 11:59
    Arnold Visser
    0

    It is a bit counter-intuitive indeed, but this works very fast. But I'm sure there will be someone to do this in a better way ;)

  • Mike Taylor 155 posts 353 karma points
    Aug 03, 2011 @ 12:09
    Mike Taylor
    0

    I've just tried this, and it's not doing the GroupedOr, it's just treating it as an "And", which is kinda what I would expect.

    It looks like it's doing:

    .Field("fieldA","fieldAValue")
    .And().Field("fieldB","fieldBValue")
    .And().GroupedOr("fieldC", value1)
    .And().GroupedOr(
    "fieldC", value2)
    .And().GroupedOr(
    "fieldC", value3)

    which, surely, is essentially the same as:

    .Field("fieldA","fieldAValue")
    .And().Field("fieldB","fieldBValue")
    .And().Field(
    "fieldC", value1)
    .And().Field(
    "fieldC", value2)
    .And().Field(
    "fieldC", value3)

     

    I need the fieldC values to be OR - 
    (fieldA:fieldAValue) AND (fieldB:fieldBValue) AND ((fieldC contains "val1" OR fieldC contains "val2")) etc 

     

    Cheers,

    Mike

  • Mike Taylor 155 posts 353 karma points
    Aug 03, 2011 @ 13:12
    Mike Taylor
    0

    OK, according to this codeplex item, GroupedOr isn't the right way to go here. Shannon recommends that to search a single field for multiple terms, you should "simply" use the Field query.

    So, my question then is - how do you group the terms if you want to do this:

    .Field("fieldA","valA")
    .And()
    .Field("fieldB","valB")
    .And()
    ( OPEN BRACKETS
         .Field("fieldC","valC1")
         .Or()
         .Field("fieldC","valC2")
         .Or()
         .Field("fieldC","valC3")
    CLOSE BRACKETS )

    This seems like a pretty straightforward thing to need to do - is it not possible? In Lucene syntax, it's possible like this:

    +fieldA:valA +fieldB:valB +(fieldC:valC1 fieldC:valC2 fieldC:valC3)

     

    Failing that, is the order you do things in relevant? For example, is this...

    [condition] .And() [condition] .Or() [condition]

    different to this...

    [condition] .Or() [condition] .And() [condition]

    Cheers,
    Mike
  • Carl Lundblad 12 posts 33 karma points
    Nov 14, 2011 @ 17:11
    Carl Lundblad
    1

    Hey, did you ever figure this one out? I'm having the exact same problem.

     

    Carl

     

    Edit:

    I just tried this out:

     

    private void AddGroupedCriteria(ref IBooleanOperation filter, string field, string value)
    {
          string[] values = value.Split(',');
          var fields = new string[values.Length];
          for (var i = 0; i < values.Length; i++)
          {
              fields[i] = field;
          }
          filter.And().GroupedOr(fields, values);

    }

     

    Ugly as it might be, it actually seems to do the trick. :)

  • Matthew Hunt 13 posts 35 karma points
    Aug 02, 2012 @ 13:32
    Matthew Hunt
    0

    I'm struggling with this also, GroupedOr is what I want, it just doesn't work how it should!!

  • Mike Taylor 155 posts 353 karma points
    Aug 02, 2012 @ 13:34
    Mike Taylor
    0

    Hi there - I just ended up using the raw lucene syntax...

  • Tom Fulton 2030 posts 4998 karma points c-trib
    Nov 05, 2012 @ 20:15
    Tom Fulton
    0

    Hi Carl,

    Thanks for the code -- works great for me!  I added it to the codeplex issue to see Shannon might have any ideas on a permanent fix.

    Thanks,
    Tom 

Please Sign in or register to post replies

Write your reply to:

Draft