This is the 3rd and last in the series on using the open source AdvancedDatabaseCrawler Lucene index. From Sitecore 6.5, Sitecore is deprecating the old Lucene index. This means that we have to redo our index work. Fortunately, Alex Shyba has created an open source module that makes indexing and retrieving easy.
This is article 3 of 3 articles:
Part 1 – Configuring the index: Using the Sitecore open source AdvancedDatabaseCrawler Lucene indexer
Part 2 – Simple search: Get latest news using Sitecore AdvancedDatabaseCrawler Lucene index
Part 3 – Multivalue search: Get items based on Metadata using Sitecore AdvancedDatabaseCrawler Lucene index
If you have not read the first article, you should read it, as it explains how to compile the module and how to set up an index that indexes your WEB database.
This is the second-most common Lucene index task: How to get a list of items scattered all over your website based on GUID values in a multilist field. For example, if you use metadata to tag pages, and you need to show a list of all pages with a certain set of metadata.
Here is my scenario: I have a list of metadata categories:
These metadata are applied to my pages through the Categories field multiselect box:
Any page can have 0-n categories. Now I would like to get all pages that have both “Childrens Books” and “Classical Literature” metdata.
My index is already set up so it indexes every field in my solution (read about the configuration of the index here), so I only have to set up a search. And thanks to Alex Shybas AdvancedDatabaseCrawler, this is easy:
using System; using System.Collections.Generic; using System.Linq; using Sitecore.Data.Items; using Sitecore.SharedSource.Searcher; using Sitecore.SharedSource.Searcher.Parameters; namespace PT.Prototype.Search { public partial class _default : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { DataBind(); } public IEnumerable<Item> GetClassicalChildrensBooks() { // The Refinements are a list of field/value searches that must be performed. // My list is simple, as I search in the field "categories" for the GUID of // "Childrens Books" and "Classical Literature" List<MultiFieldSearchParam.Refinement> refinements = new List<MultiFieldSearchParam.Refinement>(); refinements.Add(new MultiFieldSearchParam.Refinement("categories", "{4481D164-CF7C-421B-BC98-6189AB754C65}")); refinements.Add(new MultiFieldSearchParam.Refinement("categories", "{C813518E-6880-4FBE-A10F-7F8CE51AA52D}")); MultiFieldSearchParam searchParam = new MultiFieldSearchParam(); // The name of the database to search in searchParam.Database = "web"; // The language to return searchParam.Language = "en"; // The AND/OR/NOT condition between fields searchParam.InnerCondition = Sitecore.Search.QueryOccurance.Must; // The fields to search in searchParam.Refinements = refinements; // Run the Query on the index called "web" QueryRunner runner = new QueryRunner("web"); IEnumerable<SkinnyItem> items = runner.GetItems(searchParam); // Return the items found return items.Select(item => Sitecore.Context.Database.GetItem(item.ItemID)); } } }
All I need to do now is to create an asp:Repeater and databind it to the function:
<%@ Register TagPrefix="sc" Namespace="Sitecore.Web.UI.WebControls" Assembly="Sitecore.Kernel" %> <asp:Repeater ID="repClassicalChildrensBooks" DataSource="<%# GetClassicalChildrensBooks() %>" runat="server"> <HeaderTemplate> <ul> </HeaderTemplate> <FooterTemplate> </ul> </FooterTemplate> <ItemTemplate> <li> <a href="<%# Sitecore.Links.LinkManager.GetItemUrl(Container.DataItem as Sitecore.Data.Items.Item) %>"> <sc:FieldRenderer ID="FieldRenderer2" FieldName="Title" runat="server" Item="<%# Container.DataItem as Sitecore.Data.Items.Item %>" /> </a> </li> </ItemTemplate> </asp:Repeater>
If I modify the searchParam.InnerCondition to Sitecore.Search.QueryOccurance.Should, I get an “OR” clause, returning all items with that is tagged with either “Childrens Books” or “Classical Literature” (or both).
If modified to Sitecore.Search.QueryOccurance.MustNot I get a “NOT” clause, returning any item not tagged with the 2 categories.
Pingback: Using the Sitecore open source AdvancedDatabaseCrawler Lucene indexer « Brian Pedersen’s Sitecore and .NET Blog
Pingback: Get latest news using Sitecore AdvancedDatabaseCrawler Lucene index « Brian Pedersen’s Sitecore and .NET Blog
Excellent post! Thanks
LikeLike
Thanks for posting this example. To be honest I didn’t realize the MultiFieldSearchParam was doing a partial field search, so I was about to conclude I was going to have to extend Alex’s module to do just that.
LikeLike
Thanks for a good article. Nice to see some documentation on this. Docs are very sparce!
Can you describe how to use the searchParam.RelatedIds property? I have tried to use parentIds of items etc but never get any results.
LikeLike
For TemplateIDs, is the delimiter a pipe? I’m using:
searchParam.TemplateIds = “{F05D8987-0241-48A1-A3FE-8F32872867C9}|{3333EF02-EA66-4FEA-8A9B-B82A72C34756}|{91B4744D-B60F-4FA8-A420-E32E4519A1D6}”;
What I want is results that are one of those 3 templates. If I take off the last 2 GUIDs, it works for all items that are the 1st template. But with all 3, I get no results.
LikeLike
@tuesdayboozedaykc
Did you ever find a solution to your issue? I’m having a similar problem, with the caveat that if I omit searchParam.TemplateIds I yield results. Otherwise it breaks.
LikeLike
I found AdvancedDatabaseCrawler ok for simple search but not really good for advanced search it’s way too slow. The parser part needs to be rewritten in order to make it fast. the InnerCondition is only for one groupping and at the end you still end up using Lucene.Net.Search.Query againt the Index so why so much overhead for using MultiFieldSearchParam.
I am in process of making another module and improve the missing part.
Last but not least, there is no way to ask the current Sitecore Lucene Index NOT to index a single item.
LikeLike
Brian,
Very informative post. Its very helpful indeed that this module exists, so we don’t have to construct all the queries ourselves. I initially found it a little odd that this wasn’t included with sitecore (as opposed to releasing a separate module). But then in Sitecore 7, a lot of this has been included already.
I was wondering – do you know how to to startswith queries with these search parameters/refinements?
LikeLike