Help shape the future of CMS PaaS release notes! Take this quick survey and share your feedback.
Help shape the future of CMS PaaS release notes! Take this quick survey and share your feedback.
Not sure if it's trivial or not. But you're missing how expressions work and how they're translated into Elastic queries.
First I would recommend adding an enumerable to your model and then re-index.
public virtual IEnumerable<string> HeadboardTypes => return HeaderboardType.Split(',');
Then you can write your query like this:
if (tippingSearchData.Headboard != null && tippingSearchData.Headboard.Any()) { query = query.Filter(x => x.HeaderboardTypes.In( tippingSearchData.Headboard)); }
Following code doesn't work,
tp.HeadboardType.Split(',').Match(headboard.ToString())
since Split cannot be translated into an query that Elastic understands.
Edit, you might have to create a string array of tippingSearchData.Headboard, not sure if there is an In-method that supports an array of enum.
Also, why are you not using enum flags? Since you're allowing multiple values. I think Find has support that when writing queries.
Hi Johan,
you are absolutely right.. I'm still a nOOb at Epi Find and it was not trivial at all, but you helped me.
Your tip about the "In" filter in combination with the enumerable added to my model was the correct solution.
I indeed needed to convert my List<Enums> tippingSearchData.Headboard to a List<string> variant.
I couldnt follow your last comment about using enum Flags. If i can improve my code more i would love to hear about what you were suggesting exactly.
First hit on SO https://stackoverflow.com/questions/8447/what-does-the-flags-enum-attribute-mean-in-c
Oh i know what enum flags are, but i meant in combination with how you mean to use it using Epi find qeury in this case. How would a sample query look like using enum flags.
Something like this
public class TippingProduct : BaseProductContent { [EnumMany(typeof(TippingFrontEndCylinderHeadboardTypes))] [Display] public virtual TippingFrontEndCylinderHeadboardTypes HeadboardTypes { get; set; } } [Flags] public enum TippingFrontEndCylinderHeadboardTypes { None = 0, Slanted = 1, Straight = 2 } public class TippingSearchData { public TippingFrontEndCylinderHeadboardTypes HeadboardTypes { get; set; } } public static dynamic TippingProducts(TippingSearchData tippingSearchData) { IClient client = SearchClient.Instance; var query = client.Search<TippingProduct>() .FilterForVisitor() .Filter(x => x.ShowInList.Match(true)); if (tippingSearchData.HeadboardTypes != TippingFrontEndCylinderHeadboardTypes.None) { query = query.Filter(x => x.HeadboardTypes.Match(tippingSearchData.HeadboardTypes)); } var res = query.GetContentResult(); return new { items = res.Count() }; }
Not sure what your EnumMany attribute and edirot supports, so it probably needs to be rewritten. But the main point is that there's no need for an array of enum values, since it's already supported by flags and bit-wise operations.
Yes now i remember again that i did that, i wanted to make my property indeed of return the Enum instead of a string, but i got a error.
[EnumMany(typeof(TippingFrontEndCylinderHeadboardType))] //[BackingType(typeof(PropertyString))] [Display(Order = 8, Name = "Headboard Type", GroupName = Logic.Constants.TabNames.Filters, Description = "Filter Headboard Type - Frontend Cylinder")] public virtual TippingFrontEndCylinderHeadboardType HeadboardType { get; set; }
But i got this error The type Logic.Enums.TippingFrontEndCylinderHeadboardType can not be mapped to a MetaDataType .
I thought maybe needed to add the backing type property string but with that active i got error: The property 'HeadboardType' on content type 'TippingProduct' is of type 'Logic.Enums.TippingFrontEndCylinderHeadboardType' that cannot be backed by PropertyString, it only only supports types String.
I think it must be my enumMany class that conflicts but could not figure out what.
public class EnumManyAttribute : SelectManyAttribute, IMetadataAware { public Type EnumType { get; set; } public EnumManyAttribute(Type enumType) { EnumType = enumType; } public new void OnMetadataCreated(ModelMetadata metadata) { SelectionFactoryType = typeof(EnumSelectionFactory<,>).MakeGenericType(EnumType, typeof(string)); base.OnMetadataCreated(metadata); } }
It basically a generic class
public class EnumSelectionFactory<TEnum, TUnderlying> : BaseService, ISelectionFactory { public IEnumerable<ISelectItem> GetSelections(ExtendedMetadata metadata) { return Enum.GetValues(typeof(TEnum)) .Cast<TEnum>() .Select(s => new SelectItem { Value = Convert.ChangeType(s, typeof(TUnderlying)), Text = ValueName(s as Enum) }); } private static string ValueName(Enum value) { var culture = WebContext.Current.CurrentCulture; //var resourceKey = $"{value.GetType().FullName}.{value}"; //var translationService = ServiceLocator.Current.GetInstance<LocalizationService>(); return value.TranslateByCulture(culture); } }
Because i needed to have the string localized , so i created this, but maybe you can see what could be the issue here. Because the Enum Flags method would be a lot better and easier to understand then my 'workaround'..
Thanks again so far for your input Johan.. Lots of gratitude and appreciation.
Hi guys,
my problem:
i have a checkbox property on a catalogitem.
the enum looks like this:
now i want to filter on headboardtype
So the property HeadBoardType of my TippingProduct saves the data as comma seperated string.
When searching using epifind i sent a List headboards and want a filter on all my TippingProduct pages where the HeadBoardType property contains one of the items from the list.
You can see in my filter builder i had a aggregate uncommented. So that works good if each TippingProduct only has 1 checkbox selected, because then its not a comma seperated string. But once 1 tipping product has 2 checkboxes selected then that one is not found. Which is logical because it will not match. But my second approach trying to split and then check doesnt work either. So i must be missing something trivial here.