So I've done that, and now I've edited the method in EntitiesController. I've commented above the line I added.
private IEnumerable<EntityBasic> ExamineSearch(string query, UmbracoEntityTypes entityType, int pageSize, int pageIndex, out int totalFound, string searchFrom = null)
{
//TODO: We need to update this to support paging
var sb = new StringBuilder();
string type;
var searcher = Constants.Examine.InternalSearcher;
var fields = new[] { "id", "__NodeId" };
//TODO: WE should really just allow passing in a lucene raw query
switch (entityType)
{
case UmbracoEntityTypes.Member:
searcher = Constants.Examine.InternalMemberSearcher;
type = "member";
fields = new[] { "id", "__NodeId", "email", "loginName"};
if (searchFrom != null && searchFrom != Constants.Conventions.MemberTypes.AllMembersListId && searchFrom.Trim() != "-1")
{
sb.Append("+__NodeTypeAlias:");
sb.Append(searchFrom);
sb.Append(" ");
}
break;
case UmbracoEntityTypes.Media:
type = "media";
var mediaSearchFrom = int.MinValue;
if (Security.CurrentUser.StartMediaId > 0 ||
//if searchFrom is specified and it is greater than 0
(searchFrom != null && int.TryParse(searchFrom, out mediaSearchFrom) && mediaSearchFrom > 0))
{
sb.Append("+__Path: \\-1*\\,");
sb.Append(mediaSearchFrom > 0
? mediaSearchFrom.ToString(CultureInfo.InvariantCulture)
: Security.CurrentUser.StartMediaId.ToString(CultureInfo.InvariantCulture));
sb.Append("\\,* ");
}
break;
case UmbracoEntityTypes.Document:
type = "content";
var contentSearchFrom = int.MinValue;
if (Security.CurrentUser.StartContentId > 0 ||
//if searchFrom is specified and it is greater than 0
(searchFrom != null && int.TryParse(searchFrom, out contentSearchFrom) && contentSearchFrom > 0))
{
sb.Append("+__Path: \\-1*\\,");
sb.Append(contentSearchFrom > 0
? contentSearchFrom.ToString(CultureInfo.InvariantCulture)
: Security.CurrentUser.StartContentId.ToString(CultureInfo.InvariantCulture));
sb.Append("\\,* ");
}
break;
default:
throw new NotSupportedException("The " + typeof(EntityController) + " currently does not support searching against object type " + entityType);
}
var internalSearcher = ExamineManager.Instance.SearchProviderCollection[searcher];
//build a lucene query:
// the __nodeName will be boosted 10x without wildcards
// then __nodeName will be matched normally with wildcards
// the rest will be normal without wildcards
//check if text is surrounded by single or double quotes, if so, then exact match
var surroundedByQuotes = Regex.IsMatch(query, "^\".*?\"$")
|| Regex.IsMatch(query, "^\'.*?\'$");
if (surroundedByQuotes)
{
//strip quotes, escape string, the replace again
query = query.Trim(new[] { '\"', '\'' });
query = Lucene.Net.QueryParsers.QueryParser.Escape(query);
//nothing to search
if (searchFrom.IsNullOrWhiteSpace() && query.IsNullOrWhiteSpace())
{
totalFound = 0;
return new List<EntityBasic>();
}
//update the query with the query term
if (query.IsNullOrWhiteSpace() == false)
{
//add back the surrounding quotes
query = string.Format("{0}{1}{0}", "\"", query);
//node name exactly boost x 10
sb.Append("+(__nodeName: (");
sb.Append(query.ToLower());
sb.Append(")^10.0 ");
foreach (var f in fields)
{
//additional fields normally
sb.Append(f);
sb.Append(": (");
sb.Append(query);
sb.Append(") ");
}
sb.Append(") ");
}
}
else
{
var trimmed = query.Trim(new[] {'\"', '\''});
//nothing to search
if (searchFrom.IsNullOrWhiteSpace() && trimmed.IsNullOrWhiteSpace())
{
totalFound = 0;
return new List<EntityBasic>();
}
//update the query with the query term
if (trimmed.IsNullOrWhiteSpace() == false)
{
query = Lucene.Net.QueryParsers.QueryParser.Escape(query);
var querywords = query.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
//node name exactly boost x 10
sb.Append("+(__nodeName:");
sb.Append("\"");
sb.Append(query.ToLower());
sb.Append("\"");
sb.Append("^10.0 ");
//node name normally with wildcards
sb.Append(" __nodeName:");
sb.Append("(");
foreach (var w in querywords)
{
sb.Append(w.ToLower());
sb.Append("* ");
}
sb.Append(") ");
foreach (var f in fields)
{
//additional fields normally
sb.Append(f);
sb.Append(":");
sb.Append("(");
foreach (var w in querywords)
{
//I added this line below
sb.Append("*");
sb.Append(w.ToLower());
sb.Append("* ");
}
sb.Append(")");
sb.Append(" ");
}
sb.Append(") ");
}
}
//must match index type
sb.Append("+__IndexType:");
sb.Append(type);
var raw = internalSearcher.CreateSearchCriteria().RawQuery(sb.ToString());
var result = internalSearcher
//only return the number of items specified to read up to the amount of records to fill from 0 -> the number of items on the page requested
.Search(raw, pageSize * (pageIndex + 1));
totalFound = result.TotalItemCount;
var pagedResult = result.Skip(pageIndex);
switch (entityType)
{
case UmbracoEntityTypes.Member:
return MemberFromSearchResults(pagedResult.ToArray());
case UmbracoEntityTypes.Media:
return MediaFromSearchResults(pagedResult);
case UmbracoEntityTypes.Document:
return ContentFromSearchResults(pagedResult);
default:
throw new NotSupportedException("The " + typeof(EntityController) + " currently does not support searching against object type " + entityType);
}
}
It hasn't worked, I get a YSOD error message.
Please can you help me, or tell me I'm doing it wrong, or point me in the right direction.
Lucene.Net.QueryParsers.ParseException occurred
HResult=0x80131500
Message=Cannot parse '+(__nodeName:"gmail"^10.0 __nodeName:(gmail* ) id:(*gmail* ) __NodeId:(*gmail* ) ) +__IndexType:content': '*' or '?' not allowed as first character in WildcardQuery
Source=Lucene.Net
StackTrace:
at Lucene.Net.QueryParsers.QueryParser.Parse(String query)
at Examine.LuceneEngine.SearchCriteria.LuceneSearchCriteria.RawQuery(String query)
at Umbraco.Web.Editors.EntityController.ExamineSearch(String query, UmbracoEntityTypes entityType, Int32 pageSize, Int32 pageIndex, Int32& totalFound, String searchFrom) in C:\Users\paul.seal.MEDIANETWORK\Documents\GitHub\Umbraco-CMS\src\Umbraco.Web\Editors\EntityController.cs:line 781
at Umbraco.Web.Editors.EntityController.ExamineSearch(String query, UmbracoEntityTypes entityType, String searchFrom) in C:\Users\paul.seal.MEDIANETWORK\Documents\GitHub\Umbraco-CMS\src\Umbraco.Web\Editors\EntityController.cs:line 597
at Umbraco.Web.Editors.EntityController.SearchAll(String query) in C:\Users\paul.seal.MEDIANETWORK\Documents\GitHub\Umbraco-CMS\src\Umbraco.Web\Editors\EntityController.cs:line 118
at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass10.<GetExecutor>b__9(Object instance, Object[] methodParameters)
at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary`2 arguments, CancellationToken cancellationToken)
Inner Exception 1:
ParseException: '*' or '?' not allowed as first character in WildcardQuery
'*' or '?' not allowed as first character in WildcardQuery
My best guess is that leading wildcards are not allowed in your configuration. If you are using Examine there is an option enableLeadingWildcard in your ExamineSettings.config
Why are you searching on _ fields those are not tokensied. So _nodeName should be nodeName. This wont be the error but searching on _ fields which umbraco examine uses for sorting may be give you incorrect results. In fact update to use non _ fields take of the leading wildcard and see if that works.
You are using standard analyser so it should see the email. If it dont work then we can look at leading wildcard again however get rid of __ fields and replace with actual names.
Search by member email address domain part
Hi all I want to be able to search in Umbraco by the domain part of a member's email address.
I've been advised to add this setting to enable leading wildcards
So I've done that, and now I've edited the method in EntitiesController. I've commented above the line I added.
It hasn't worked, I get a YSOD error message.
Please can you help me, or tell me I'm doing it wrong, or point me in the right direction.
Do you have a stacktrace?
I get this if I debug
My best guess is that leading wildcards are not allowed in your configuration. If you are using Examine there is an option
enableLeadingWildcard
in your ExamineSettings.configHi Damian I've already done that. I put it in the first part of my question.
Thanks for trying to help me.
Kind regards
Paul
Paul,
Why are you searching on _ fields those are not tokensied. So _nodeName should be nodeName. This wont be the error but searching on _ fields which umbraco examine uses for sorting may be give you incorrect results. In fact update to use non _ fields take of the leading wildcard and see if that works.
You are using standard analyser so it should see the email. If it dont work then we can look at leading wildcard again however get rid of __ fields and replace with actual names.
Regards
Ismail
is working on a reply...