I'm not good at using Examine, but I tried to create search functionality with it. I tried the "Power Searching with Raw Lucene Queries" chapter at the documentation. The problem is that it doesn't always return the results I'd expect.
For example searching for "Congres Van Gelder advocaten" returns the page with that title, but only searching for "Congres Van Gelder" doesn't return any results. Another example: "BOB Borrel 13 november" returns the correct page, but "BOB Borrel" doesn't return anything. However searching for "franchisenemers" and "Recruit a Student zoekt franchisenemers" both return that page.
//Power Searching with Raw Lucene Queries
var Searcher = ExamineManager.Instance.SearchProviderCollection["ExternalSearcher"];
var searchCriteria = Searcher.CreateSearchCriteria(BooleanOperation.Or);
var term = searchString;
var luceneString = "nodeName:";
luceneString += "(+" + term.Replace(" ", " +") + ")^5 ";
luceneString += "nodeName:" + term;
var query = searchCriteria.RawQuery(luceneString);
var searchResults = Searcher.Search(query).OrderByDescending(x => x.Score);
I tried to look at the index files with Luke, but I don't really understands how that works. Could post the files here if that helps. I hope someone knows what I'm doing wrong here.
The first thing that I see is your analyzers are different for you indexer and searcher. They must be the same. I suggest that you set them both to standardAnalyzer as that is what I find works best for free text searching.
If they are not set the same you will get strange results.
To put it crudely, think of it as the language that it reads and writes. If it is writing in French but reading in English it will see some words but not all.
Im not sure why you have to set it twice other than they are two configs for two totally different pieces of the puzzle :)
//Build the luceneString which will be used for searching.
var term = searchString;
var luceneString = "nodeName:";
luceneString += "(+" + term.Replace(" ", " +") + ")^5 ";
luceneString += "nodeName:" + term;
#region Member
//Power Searching the members with Raw Lucene Queries
var searcherMember = ExamineManager.Instance.SearchProviderCollection["ExternalMemberSearcher"];
var searchCriteriaMember = searcherMember.CreateSearchCriteria(BooleanOperation.Or);
var queryMember = searchCriteriaMember.RawQuery(luceneString);
var searchResultsMember = searcherMember.Search(queryMember);
//Add the member results to the results list.
if (searchResultsMember.Count() > 0)
{
//Get the member detail page id from the web.config
int memberDetailId = Convert.ToInt32(ConfigurationManager.AppSettings["memberDetailId"]);
string url = library.NiceUrl(memberDetailId);
results.AddRange(
searchResultsMember.Select(r =>
{
return new Search()
{
Name = r.Fields["nodeName"],
Text = "", //TODO use member quote or other field here
Url = url + "?member=" + r.Id
};
})
);
}
#endregion
When I search for "13" I don't get any members, but when I search for "test 13" I get all the members which have 13 in one of their fields (for example in the address). Here is how the luceneString variable looks like: "13" - "nodeName:(+13)^5 nodeName:13" | "test 13" "nodeName:(+test +13)^5 nodeName:test 13". Any idea why I don't get any members when I only search for "13".
Here is a quote from the documentation: "Let's say we want to do a search with a phrase, boost exact matches, find results that contain any of the parts of our search phrase. The Fluent API will not be able to do this.". I want to do the "find results that contain any of the parts of our search phrase" so that's why I thought I couldn't use the Fluent API.
I now have this code, but it doesn't return anything:
Sorry your example doesn't work because .MultipleCharacterWildcard() returns an IExamineValue which you can't do a .Replace(" "," +") on. Already tried this:
Ah ok. So I would now try and do the query with fluent api without the boosting. Get it working so i get expected results. Then write out to trace the generated query and then paste that into luke and add the boosting bit test till it works then use that as the raw query template.
The problem is that I couldn't get the expected search results using the fluent api. That's why I started using the raw query template. I've got the feeling that I'm almost there and the search results already return a lot more result than when I used the fluent api, but it's just strange that somehow the second word seems to return more results. "test 13" returns more results with "13" in it and "13 test" returns more results with "test" in it.
It's still a shame that searching in Umbraco is this hard. When I used XSLT search in 4.0 websites that always seemed much easier.
Ok what I'm doing now is a big hack, but until I find a good solution it seems to work :-). Somehow all words after the first word are searched better. So for now I got this ugly solution:
//Somehow searching works better on all words after the first word so for now we'll use a GUID as the first search word and use the search string as the other words.
searchString = "0589157e-a3fa-4b31-ab7d-dcfdb9976d77 " + searchString;
//Build the luceneString which will be used for searching.
var term = searchString;
var luceneString = "nodeName:";
luceneString += "(+" + term.Replace(" ", " +") + ")^5 ";
luceneString += "nodeName:" + term;
I now get all the search results and when I search for "test 13" or "13 test" I also get the same results.
Not getting all search results with Examine
Hello,
I'm not good at using Examine, but I tried to create search functionality with it. I tried the "Power Searching with Raw Lucene Queries" chapter at the documentation. The problem is that it doesn't always return the results I'd expect.
For example searching for "Congres Van Gelder advocaten" returns the page with that title, but only searching for "Congres Van Gelder" doesn't return any results. Another example: "BOB Borrel 13 november" returns the correct page, but "BOB Borrel" doesn't return anything. However searching for "franchisenemers" and "Recruit a Student zoekt franchisenemers" both return that page.
Here is some of my code:
ExamineIndex.config
ExamineSettings.config
Search code:
I tried to look at the index files with Luke, but I don't really understands how that works. Could post the files here if that helps. I hope someone knows what I'm doing wrong here.
Jeroen
Hi Jeroen
The first thing that I see is your analyzers are different for you indexer and searcher. They must be the same. I suggest that you set them both to standardAnalyzer as that is what I find works best for free text searching.
If they are not set the same you will get strange results.
Give that a go and see how you get on.
Peter
Hi Peter,
Thanks for spotting that! Now both analyzers are the same (why do you need to set it twice?) and all the search words return the expected results :-).
Jeroen
Glad that sorted it out.
To put it crudely, think of it as the language that it reads and writes. If it is writing in French but reading in English it will see some words but not all.
Im not sure why you have to set it twice other than they are two configs for two totally different pieces of the puzzle :)
Peter
Hello,
I've got another question about the results. I'm now also trying to search for members, but again I'm not getting the results I expected.
Here is some of my code again:
ExamineIndex.config
ExamineSettings.config
Search code:
When I search for "13" I don't get any members, but when I search for "test 13" I get all the members which have 13 in one of their fields (for example in the address). Here is how the luceneString variable looks like: "13" - "nodeName:(+13)^5 nodeName:13" | "test 13" "nodeName:(+test +13)^5 nodeName:test 13". Any idea why I don't get any members when I only search for "13".
Jeroen
Some more info. When I search for "test 13" I get different results than when I search for "13 test".
Jeroen
Jeroen,
Any reasonwhy you are using raw queries and not the fluent api? Also end of term add +"*" to make it wildcard.
Regards
Ismail
Hi Ismail,
Here is a quote from the documentation: "Let's say we want to do a search with a phrase, boost exact matches, find results that contain any of the parts of our search phrase. The Fluent API will not be able to do this.". I want to do the "find results that contain any of the parts of our search phrase" so that's why I thought I couldn't use the Fluent API.
I now have this code, but it doesn't return anything:
Jeroen
Do you have an example how it should work with the Fluent API? If that works I guess it's better to use that.
Jeroen
Jeroen,
Ah ok I see. Looking at the query the * needs to be at end of keywords with in the brackets? So replace term with
term.MultipleCharacterWildcard().Replace(" "," +")
you will need reference to examine namespace to get that extension method.
Regards
Ismail
Sorry your example doesn't work because .MultipleCharacterWildcard() returns an IExamineValue which you can't do a .Replace(" "," +") on. Already tried this:
term.Replace(" ", " +").MultipleCharacterWildcard()
but that also doesn't work because .MultipleCharacterWildcard() doesn't return a string.
Jeroen
Ah ok. So I would now try and do the query with fluent api without the boosting. Get it working so i get expected results. Then write out to trace the generated query and then paste that into luke and add the boosting bit test till it works then use that as the raw query template.
Regards
Ismail
The problem is that I couldn't get the expected search results using the fluent api. That's why I started using the raw query template. I've got the feeling that I'm almost there and the search results already return a lot more result than when I used the fluent api, but it's just strange that somehow the second word seems to return more results. "test 13" returns more results with "13" in it and "13 test" returns more results with "test" in it.
It's still a shame that searching in Umbraco is this hard. When I used XSLT search in 4.0 websites that always seemed much easier.
Jeroen
Ok what I'm doing now is a big hack, but until I find a good solution it seems to work :-). Somehow all words after the first word are searched better. So for now I got this ugly solution:
I now get all the search results and when I search for "test 13" or "13 test" I also get the same results.
Jeroen
what happens when you make wildcard so if you have terms with space add * to each term? try it in luke first see if that works.
Regards
Ismail
is working on a reply...