You should be able to add JsonIgnore attribute on the property to exclude it or setup a convention and use the ExcludeField() extension method.
Frederik
One way would be no enumerate all fields in type and include all excluding LinkUrl.
var q = SearchClient.Instance.Search<PageData>().For("foo").InField(x => x.ExternalURL).InField(x => x.Name);
Which is a but cumbersome. Maybe this tiny helper method may come handy:
public static class IQueriedSearchExtensions
{
public static IQueriedSearch<TSource, QueryStringQuery> ExcludeFields<TSource>(
this IQueriedSearch<TSource, QueryStringQuery> search,
params Expression<Func<TSource, string>>[] fieldSelectors)
{
var excludedFields = fieldSelectors.Select(fs => fs.GetFieldPath());
var properties = TypeDescriptor.GetProperties(typeof(TSource));
var includingFields = properties.Cast<PropertyDescriptor>().Select(p => p.Name).Except(excludedFields);
includingFields.ForEach(name => search = search.InField(name));
return search;
}
}
Then you can type something like similar:
var q = SearchClient.Instance.Search<ArticlePage>().For("adsf").ExcludeFields(x => x.LinkURL, x => x.Name);
Hi
Frederik: Wouldn't JsonIgnore remove the value from the index? I want the value in the index, but I do not want to search in it.
Valdis: I will check your method out. Thank you.
Valdis: I can not get this to work properly. The code seems to just remove all hits for some reason. When I debug I can see that your code includes i.e the field MainIntro and I know the text I'm searching for is in that field, but still no hits.
To clearify:
When i use
_client.Instance().Search<IBasePageData>(Language.Norwegian)
.For(searchParameters.Query)
.InField(x => x.MainIntro);
it gets the result that I'm excpecting.
When I use
_client.Instance().Search<IBasePageData>(Language.Norwegian)
.For(searchParameters.Query)
.ExcludeFields(x => x.LinkURL);
There is no hits at all.
Do you have any idea what is happening?
The ExcludeFields helper method is wrong as the field name in the index isn't .GetFieldPath() but:
client.Instance().Conventions.FieldNameConvention
.GetFieldNameForSearch(fieldSelector, Language.Norwegian);
It isn't straight forward writing the ExcludeFields as you have to get the right fieldnames for the includingFields as well. I would say that your best option is to use InFields(x => x.MainIntro, x=> ...)
Oh I see, and yes as Henrik said - it would be easier not to try to float against the stream :) and use InField/s() methods.
Anyway, if you are willing to take ExcludeFields approach here is a snippet to be enchanced further (generates correct field names):
public static class IQueriedSearchExtensions
{
public static IQueriedSearch<TSource, QueryStringQuery> ExcludeFields<TSource>(
this IQueriedSearch<TSource, QueryStringQuery> search,
params Expression<Func<TSource, object>>[] fieldSelectors)
{
var excludedFields = fieldSelectors.Select(fs => SearchClient.Instance.Conventions.FieldNameConvention.GetFieldNameForSearch(fs, Language.Norwegian));
var properties = TypeDescriptor.GetProperties(typeof(TSource));
var lambdaExpressions =
properties.Cast<PropertyDescriptor>()
.Select(pd => Expression.Lambda(Expression.PropertyOrField(Expression.Parameter(typeof(TSource)), pd.Name)));
var includedFields =
lambdaExpressions.Select(z1 => SearchClient.Instance.Conventions.FieldNameConvention.GetFieldNameForSearch(z1, Language.Norwegian))
.Except(excludedFields);
includedFields.ForEach(name => search = search.InField(name));
return search;
}
}
There is small side effect for this approach - if you are search for string query and include "$number" field - you most probably will get NumberFormatException. So you would need to exclude all those field as well which may end up with almost the same code as for InFields :) just inverted
Hi!
The only way we have been successful with excluding properties in EPiServer Find is with [JsonIgnore] and Searchable(false). Without Searchable(false) JsonIgnore doesn't work.
[JsonIgnore]
[Display(
Name = "Some Field not 2 show",
GroupName = SystemTabNames.Content,
Order = 600), Searchable(false)]
public virtual XhtmlString HiddenFromSearchResults { get; set; }
Hi,
I can give a short comment about the difference between [JsonIgnore] and Searchable(false).
[JsonIgnore]: this removes the property from beeing serialized and put in the index (as a HiddenFromSearchResults property in the json)
Searchable(false/true): This tells if the property should be searchable or not using the internal search and is also used for Find UnifiedSearch. As for Find all the searchable properties are mapped into the SearchText property of the ISearchContent interface (and therefore are searchable even if the HiddenFromSearchResult property isn't serialized and indexed).
So if you want to include/exclude properties from UnifiedSearch you only have to set Searchable(true/false) but if you want to completly exclude it from the index you also have to mark it as [JsonIgnore].
/Henrik
@Henrik Lindström: While we are on the subject, would it be possible to exclude a field from being searched via [Searchable(false)] but still have that property map to SearchText? Specifically, we need to exclude the content of a specific page type from being searchable from UnifiedSearch while still maintaining its excerpt.
@anders.jansson No, not without manully adding the text to the excerpt in the result. The simplest way to do that is to add the property that you want to get back but not have searchable into the SearchMetaData dictionary:
client.Conventions.UnifiedSearchRegistry
.ForInstanceOf<MyType>()
.CustomizeProjection(
builder => builder.ProjectMetaDataFrom<NativeSearchContent>(x => x.SearchMetaData.AppendRange(new Dictionary<string, IndexValue> { { "key", x.MyProperty } })));
Then you can add it to the excerpt manually when fetching the result by grabbing it from the MetaData-property:
hit.MetaData["key"]
/Henrik
Hi
Is it possible to exclude a field in the index from search. The reason is that i want the value LinkUrl to be a part of the index because I need it in my searchresult, but I do not want to search in it.
I.e a search for "Pages" or "Templates" would yield an enormous amount of hits.
Is this possible to achieve?