+1-888-365-2779
Try Now
More in this section

Forums / Developing with Sitefinity / Custom Module and indexing issues

Custom Module and indexing issues

8 posts, 0 answered
  1. Ly
    Ly avatar
    10 posts
    Registered:
    21 Oct 2010
    22 Dec 2011
    Link to this post
    Hi,

    I created a custom class called CustomRes and have implemented a SearchIndex for it.
    Problem is when performing a search on some words, zero results are returned even when they're in the CustomRes item.
    E.g, 'unique', 'something' - first I thought it was the number of characters but it's hit and miss.

    fieldsInfoProvider.xml
    <?xml version="1.0" encoding="utf-8"?>
    <fields>
      <field name="title" weight="1" indexAttribute="" filterTag="title" filterAttributes="" />
      <field name="guid" weight="1" indexAttribute="" filterTag="guid" filterAttributes="" />
      <field name="ItemID" weight="1" indexAttribute="" filterTag="guid" filterAttributes="" />
      <field name="keywords" weight="1" indexAttribute="content" filterTag="meta" filterAttributes="name:keywords;" />
      <field name="description" weight="1" indexAttribute="content" filterTag="meta" filterAttributes="name:description;" />
      <field name="script" weight="-1" indexAttribute="" filterTag="script" filterAttributes="" />
      <field name="style" weight="-1" indexAttribute="" filterTag="style" filterAttributes="" />
    </fields>

    public IList<ResultItem> Search(string searchQuery, string indexName, int startIndex, int max, string mode, bool escapeChars, out int totalItems)
                {
     
                    IList<ResultItem> result = new List<ResultItem>();
                    string[] fields = GetFields(indexName);
                    string indexDirectory = PathUtil.GetIndexPhysicalPath(indexName);
                    IndexSearcher searcher = new IndexSearcher(indexDirectory);
     
                    QueryParser.Operator searchMode = QueryParser.AND_OPERATOR;
     
                    MultiFieldQueryParser parser = new MultiFieldQueryParser(fields, new StandardAnalyzer());
     
                    if (!String.IsNullOrEmpty(mode)
                        && mode == "AnyWord")
                    {
                        searchMode = QueryParser.OR_OPERATOR;
                    }
                    parser.SetDefaultOperator(searchMode);
     
                    if (escapeChars)
                    {
                        searchQuery = QueryParser.Escape(searchQuery);
                    }
     
                    Query query = searcher.Rewrite(parser.Parse(searchQuery));
                    Highlighter highlighter = new Highlighter(new QueryScorer(query));
                    Hits hits = searcher.Search(query, Sort.INDEXORDER);
     
                    totalItems = hits.Length();
                    if (max == 0)
                        max = totalItems;
                    else if (startIndex + max > totalItems)
                        max = totalItems;
                    else
                        max = startIndex + max;
     
                    for (int i = startIndex; i < max; i++)
                    {
                        Document doc = hits.Doc(i);
                        ResultItem item = new ResultItem();
                        item.Title = doc.Get("title");
                        item.Url = ResolveUrl(doc.Get("path"));
                        item.Score = hits.Score(i);
     
                        StringBuilder snippet = new StringBuilder();
                        bool lastAppendedIsSeparator = false;
                        for (int k = 0; k < fields.Length; k++)
                        {
                            string field = fields[k];
                            switch (field.ToLower())
                            {
                                case "title":
                                case "path":
                                case "keywords":
                                case "description":
                                    continue;
                            }
                            string[] values = doc.GetValues(field);
                            if (values != null && values.Length > 0)
                            {
                                for (int j = 0; j < values.Length; j++)
                                {
                                    if (values[j].Length > 0)
                                    {
                                        snippet.Append(values[j]);
                                        lastAppendedIsSeparator = false;
                                        if (j < values.Length - 1)
                                        {
                                            snippet.AppendLine(SearchManager.SEARCH_RESULTS_SEPARATOR);
                                            lastAppendedIsSeparator = true;
                                        }
                                    }
                                }
                            }
                            if (k < fields.Length - 1 && !lastAppendedIsSeparator)
                            {
                                snippet.AppendLine(SearchManager.SEARCH_RESULTS_SEPARATOR);
                                lastAppendedIsSeparator = true;
                            }
                        }
                        string[] bestFragments = highlighter.GetBestFragments(new StandardAnalyzer(), fields[0], snippet.ToString(), 5);
                        //item.Snippet = String.Join(SearchManager.SEARCH_RESULTS_SEPARATOR, bestFragments);
                        item.Snippet = snippet.ToString();
                        item.Snippet.TrimEnd(' ', '.');
                        item.Snippet += SearchManager.SEARCH_RESULTS_SEPARATOR;
                        result.Add(item);
                    }
                    searcher.Close();
                    return result;
                }

    part of CustomResIndexerInfo.cs
    protected virtual string GetTagData()
            {
                StringBuilder builder = new StringBuilder();
                var titleData = HttpUtility.HtmlEncode(Convert.ToString(content.GetMetaData("Title")));
                var descriptionData = content.Content;
     
                builder.AppendLine();
                builder.Append("<Title>");
                builder.Append(titleData);
                builder.Append("</Title>");
                builder.AppendLine();
                builder.Append("<Description>");
                builder.Append(descriptionData);
                builder.Append("</Description>");
     
                return builder.ToString();
    }
  2. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    25 Nov 2016
    22 Dec 2011
    Link to this post
    Hi,

    Where you pass the string that contains 'unique', 'something' etc? Also I see that you have some code which is part of the SeachManager and not the index provider. How you pass the content you want to index to the manager and inside of which stage of the content lifecycle?

    Regards,
    Ivan Dimitrov
    the Telerik team
    Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
  3. Ly
    Ly avatar
    10 posts
    Registered:
    21 Oct 2010
    23 Dec 2011
    Link to this post
    I pass the string into this function in my results.ascx.cs:

    public IList<CustomRes> GetCustomRessByKeyword(bool isPublished, string keyword)
    {
        int count;
        CustomSearchResult cr = new CustomSearchResult();
        IList<ResultItem> results = cr.Search(keyword, "CustomRes-Index", 0, 200, "AnyWord", true, out count);  
        IList<CustomRes> list = new List<CustomRes>();
        foreach (var r in results)
        {
            string id = r.Snippet.Substring(0, 36);
            CustomRes sr = GetCustomResById(new Guid(id), true);

            list.Add(sr);
        }

        return list;
    }

    CustomResIndexProvider.cs:
    namespace Ly.Sitefinity.Modules.CustomResources
    {
        /// <summary>
        /// Represents information for news to be indexed.
        /// </summary>
        public class CustomResourceIndexProvider : ContentIndexProvider
        {
            public CustomResourceIndexProvider()
            {
                CustomResourcesManager = new CustomResourcesManager();
            }
     
            /// <summary>
            /// Defines the name of the provider. This name is used to manage providers within Indexing Service.
            /// </summary>
            public override string Name
            {
                get { return "CustomResourceIndexProvider"; }
            }
     
            /// <summary>
            /// Provides detailed description of the provider
            /// </summary>
            public override string Description
            {
                get { return "Provides indexing of Custom Resources"; }
            }
     
            /// <summary>
            /// Gets the content item key implicitly. This property should be overriden in the
            /// derived classes so that 2 different controls deriving from this one can be used together.
            /// </summary>
            /// <value>The content item key implicitly.</value>
            protected override string ContentItemKeyImpl
            {
                get { return "CustomResourceItem"; }
            }
     
            /// <summary>
            /// Gets the content provider key implicitly. This property should be overriden in the
            /// derived classes so that 2 different controls deriving from this one can be used together.
            /// </summary>
            /// <value>The content provider key implicitly.</value>
            protected override string ContentProviderKeyImpl
            {
                get { return "CustomResourceProv"; }
            }
     
            /// <summary>
            /// Gets the name of the default story data provider.
            /// </summary>
            /// <returns>The name of the default news data provider.</returns>
            protected override string GetDefaultContentProvider()
            {
                if (!string.IsNullOrEmpty(CustomResourceProvider))
                {
                    return CustomResourceProvider;
                }
                return CustomResourcesManager.DefaultProvider;
            }
     
            /// <summary>
            /// Gets the filter expression - specifying the given filter will ignore culture on the
            /// provider level and search will index all content, regardless of localization. You
            /// are of course free to modify the filter expression as you wish.
            /// </summary>
            public override string FilterExpression
            {
                get
                {
                    // return "Title='InVariantCulture';";
                    return string.Empty;
                }
            }
     
            /// <summary>
            /// Gets the URL to a single content item. This method is invoked for every item that
            /// is binding to the list. By default the item ID is appended to the query string portion
            /// of the URL.
            /// </summary>
            /// <returns>String containing the URL address.</returns>
            /// <param name="contentItem">
            /// <param name="singleItemUrl">Url of the page where single stories are displayed</param>
            /// <param name="culture">Culture of the item</param>
            ///     The <see cref="Telerik.Cms.Engine.IContent">IContent</see> item that is currently
            ///     binding.
            /// </param>
            protected override string GetItemUrl
                (
                IContent contentItem,
                string singleItemUrl,
                CultureInfo culture )
            {
                if (String.IsNullOrEmpty(singleItemUrl))
                {
                    singleItemUrl = contentItem.Url;
                }
                 
                return singleItemUrl;
            }
     
            protected override IIndexerInfo GetIndexerInfo(string path, IContent content)
            {
                return new CustomResourceIndexerInfo(path, content);
            }
             
            private string CustomResourceProvider;
            private readonly CustomResourcesManager CustomResourcesManager;
        }
    }

    What I do is:
    1.  Sitefinity -> Modules -> CustomResource -> add new item and fill in the details
    2.  Administration -> Custom REsource -> Start Indexing
    3.  On search.aspx I have a search bar where you type in the keywords and passes the keyword via the querystring
    4.  Redirects to the results.aspx (results.ascx is in there) which checks the query string and performs search function and return results.

    I've stepped through the code and 'unique', 'something' is passed correctly to the results.  And those two keywords are definitely in the CustomRes items
    Not sure what you mean by the 'stage of the content lifecycle'.
  4. Ly
    Ly avatar
    10 posts
    Registered:
    21 Oct 2010
    07 Feb 2012
    Link to this post
    Hi,
    Just came back from long holidays, can someone help from the Sitefinity team?
  5. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    25 Nov 2016
    07 Feb 2012
    Link to this post
    Hi,

    Can you call SearchManager.Search and see what will be returned as a result. This is method used in SearchResults control.

    All the best,
    Ivan Dimitrov
    the Telerik team
    Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
  6. Ly
    Ly avatar
    10 posts
    Registered:
    21 Oct 2010
    08 Feb 2012
    Link to this post
    Hi Ivan,

    Calling SearchManager.Search gives me the same results but I need to use my custom search because I need to retrieve the Id of each resource

    string id = r.Snippet.Substring(0, 36); // This gets the id of the resource.  Hardcoded unfortunately.
     
  7. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    25 Nov 2016
    08 Feb 2012
    Link to this post
    Hi,

    If the Guid is added to the search result no matter it is custom or not you should be able to retrieve it from the snippet. It it possible that it is added not at the beginning. You have to observe this in debug mode.

    All the best,
    Ivan Dimitrov
    the Telerik team
    Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
  8. Ly
    Ly avatar
    10 posts
    Registered:
    21 Oct 2010
    08 Feb 2012
    Link to this post
    Ivan, the problem is NOT the GUID because I AM getting it perfectly fine.  Not worrying about that.

    The problem of this thread is I'm not able to search some keywords even it's repeated heaps of times in an item - title, content, description.  Nothing!
Register for webinar
8 posts, 0 answered