Filter by dynamic fields

Vote:
 

Let say you are indexing Product object that have some common properties but also other properties that vary based on product type.
Typically something this:

Product A: name:"Cannondale Synapse", model:"synapse", brand: "Cannondale", carbonframe: "yes", gearsystem: "Shimano Ultergra"
Product B: name:"Cannondale CAAD10", model:"CAAD 10", brand: "Cannondale", carbonframe: "no", gearsystem: "Shimano 105"
Product C: name:"Jotun lady", model:"Lady", brand: "Jotun", type: "waterpaint", drytime: "1 hour"

Product A and B are bikes, while C is paint. These have common properties (name, model, brand) and then other properties that vary by type.

How can I search and filter based on these last "dynamic" properties?

My first idea was to store them in a Dictionary property on the Products object, but I can´t get to work. Ref Twitter-conversation

The Dictionary2Find project is compiled against EPiServer.Find for CMS 7 (I´m using CMS 6), and could not get it to compile with Find version 1.0.0.170.
 

#64034
Dec 07, 2012 20:18
Vote:
 

Hi Mari,

I think Henrik may be able to help you get Dictionary2Find to work with the .NET 3.5 version. However, you should upgrade to the latest of that version (1.0.0.278 at this time).

Given that you're running build 278 you could also try to have a property of type Dictionary<string, IndexValue>. IndexValue is a special little class that can hold either a string, integer, double or datetime, which based on what you write probably would work for your needs.If you try that approach I'd love to hear how it goes.

Also, IndexValue is implicitly convertible from the above mentioned types, meaning that if you have a property named A of type Dictionary<string, IndexValue> you can do:

obj.A["a"] = 1;

obj.A["b"] = DateTime.Now;

#64036
Edited, Dec 07, 2012 22:32
Vote:
 

Tried using version 1.0.0.278 and the IndexValue class, but it fails when trying to retrieve results, see error details below.
I`ve tried indexing using both 

Facets = new Dictionary<string, IndexValue> { { "carbon", "no" }, { "gears", "Shimano 105" } }

    
and

Facets = new Dictionary<string, IndexValue> { { "carbon", new IndexValue("no") }, { "gears", new IndexValue("Shimano 105") } }

    

Unable to find a constructor to use for type EPiServer.Find.IndexValue. A class should either have a default constructor, one constructor with arguments or a constructor marked with the JsonConstructor attribute.

#64053
Dec 10, 2012 8:41
Vote:
 

Are you getting that when results are retrieved? If I recall correctly you should be able to filter by values in a dictionary with IndexValue as well as project from them. However I don't think the class was designed for actually retrieving. Not that it was explictly design not to be retrievable, but it was designed for extensibility in Unified Search.

Are you retrieving the indexed objects directly without any projection? Would adding a projection work for you?

#64054
Dec 10, 2012 8:47
Vote:
 

Did some more quick testing (see results below) - will investigate further

// works for retrieving all items
            var res1 = client.Search<ProductIndexedEntry>().
                Select(x => new ProductIndexedEntry
                {
                    Name = x.Name,
                    Model = x.Model
                }).GetResult();

            // not working - throws error specified in previous post
            var res2 = client.Search<ProductIndexedEntry>().GetResult();

            // try to filter based on Dictionary key, not working - no results
            var res3 = client.Search<ProductIndexedEntry>().Filter(
                x => x.Facets.MatchContained(a => a.Key, "carbon")
                    ).GetResult();

            // not building: "Cannot convert lambda expression to type 'EPiServer.Find.Api.Querying.Filter' because it is not a delegate type
            var res4 = client.Search<ProductIndexedEntry>().Filter(
                x => x.Facets.MatchContained(a => a.Value, new IndexValue("yes"))
                    ).GetResult();

    

#64055
Dec 10, 2012 9:22
Vote:
 

I'm a bit unsure how this works in the .NET 3.5 version but in the .NET 4/CMS 7 version you should be able to do this:

Filter(x => x.Facets["carbon"].Match("yes"))

 

#64056
Dec 10, 2012 9:33
Vote:
 

If I go back to Dictionary<string,string> querying by value works:

Filter(x => x.Facets["carbon"].Match("yes")).

I'm not able to query by key (retrieving all items that has Facets key = "someKey"), but I guess I don't need that.

#64061
Edited, Dec 10, 2012 13:05
Vote:
 

Great!

Filter(x => x.Facets["carbon"].Exists()) should give you by key I think.

#64070
Dec 10, 2012 14:39
Vote:
 

Hi Mari,

Dictionary2Find work with the latest version of Find for CMS 6R2 (1.0.0.278) and now also supports filtering on keys or values.

/Henrik

#64143
Dec 11, 2012 13:25
This topic was created over six months ago and has been resolved. If you have a similar question, please create a new topic and refer to this one.