/// <summary> Deletes an existing resource from both solr/lucene core indexes </summary>
        /// <param name="SolrDocumentUrl"> URL for the solr/lucene core used for searching for a single document within the library </param>
        /// <param name="SolrPageUrl"> URL for the solr/lucene core used for searching within a single document for matching pages </param>
        /// <param name="BibID"> Bibliographic identifier for the item to remove from the solr/lucene indexes </param>
        /// <param name="VID"> Volume identifier for the item to remove from the solr/lucene indexes </param>
        /// <returns> TRUE if successful, otherwise FALSE </returns>
        public bool Delete_Resource_From_Index(string SolrDocumentUrl, string SolrPageUrl, string BibID, string VID)
        {
            try
            {
                // Get rid of trailling '/' in solr document url
                SolrDocumentUrl = SolrDocumentUrl.Trim();
                if ((!String.IsNullOrEmpty(SolrDocumentUrl)) && (SolrDocumentUrl[SolrDocumentUrl.Length - 1] == '/'))
                {
                    SolrDocumentUrl = SolrDocumentUrl.Substring(0, SolrDocumentUrl.Length - 1);
                }

                // Get rid of trailling '/' in solr page url
                SolrPageUrl = SolrPageUrl.Trim();
                if ((!String.IsNullOrEmpty(SolrPageUrl)) && (SolrPageUrl[SolrPageUrl.Length - 1] == '/'))
                {
                    SolrPageUrl = SolrPageUrl.Substring(0, SolrPageUrl.Length - 1);
                }

                // Create the solr workers
                var solrDocumentWorker = Solr_Operations_Cache <v5_SolrDocument> .GetSolrOperations(SolrDocumentUrl);

                var solrPageWorker = Solr_Operations_Cache <Legacy_SolrPage> .GetSolrOperations(SolrPageUrl);

                // For the object, we can use the unique identifier
                solrDocumentWorker.Delete(BibID + ":" + VID);

                // For the pages, we need to search by id
                solrPageWorker.Delete(new SolrQuery("did:\"" + BibID + ":" + VID + "\""));

                // Comit the changes to the solr/lucene index
                try
                {
                    solrDocumentWorker.Commit();
                }
                catch
                {
                    Thread.Sleep(10 * 60 * 1000);
                }

                try
                {
                    solrPageWorker.Commit();
                }
                catch
                {
                    Thread.Sleep(10 * 60 * 1000);
                }

                return(true);
            }
            catch (Exception)
            {
                return(false);
            }
        }
        /// <summary> Optimize the solr/lucene core used for searching within a single document </summary>
        /// <param name="SolrPageUrl"> URL for the solr/lucene core used for searching within a single document for matching pages </param>
        public void Optimize_Page_Index(string SolrPageUrl)
        {
            // Create the solr worker
            var solrPageWorker = Solr_Operations_Cache <Legacy_SolrPage> .GetSolrOperations(SolrPageUrl);

            try
            {
                solrPageWorker.Optimize();
            }
            catch (Exception)
            {
                // Do not do anything here.  It may throw an exception when it runs very longs
            }
        }
        /// <summary> Deletes an existing resource from both solr/lucene core indexes </summary>
        /// <param name="SolrDocumentUrl"> URL for the solr/lucene core used for searching for a single document within the library </param>
        /// <param name="SolrPageUrl"> URL for the solr/lucene core used for searching within a single document for matching pages </param>
        /// <param name="BibID"> Bibliographic identifier for the item to remove from the solr/lucene indexes </param>
        /// <param name="VID"> Volume identifier for the item to remove from the solr/lucene indexes </param>
        /// <returns> TRUE if successful, otherwise FALSE </returns>
        public bool Delete_Resource_From_Index(string SolrDocumentUrl, string SolrPageUrl, string BibID, string VID)
        {
            try
            {
                // Create the solr workers
                var solrDocumentWorker = Solr_Operations_Cache <Legacy_SolrDocument> .GetSolrOperations(SolrDocumentUrl);

                var solrPageWorker = Solr_Operations_Cache <Legacy_SolrPage> .GetSolrOperations(SolrPageUrl);

                // For the object, we can use the unique identifier
                solrDocumentWorker.Delete(BibID + ":" + VID);

                // For the pages, we need to search by id
                solrPageWorker.Delete(new SolrQuery("did:\"" + BibID + ":" + VID + "\""));

                // Comit the changes to the solr/lucene index
                try
                {
                    solrDocumentWorker.Commit();
                }
                catch
                {
                    Thread.Sleep(10 * 60 * 1000);
                }

                try
                {
                    solrPageWorker.Commit();
                }
                catch
                {
                    Thread.Sleep(10 * 60 * 1000);
                }

                return(true);
            }
            catch (Exception)
            {
                return(false);
            }
        }
        /// <summary> Optimize the solr/lucene core used for searching within a single document </summary>
        /// <param name="SolrPageUrl"> URL for the solr/lucene core used for searching within a single document for matching pages </param>
        public void Optimize_Page_Index(string SolrPageUrl)
        {
            // Get rid of trailling '/' in solr page url
            SolrPageUrl = SolrPageUrl.Trim();
            if ((!String.IsNullOrEmpty(SolrPageUrl)) && (SolrPageUrl[SolrPageUrl.Length - 1] == '/'))
            {
                SolrPageUrl = SolrPageUrl.Substring(0, SolrPageUrl.Length - 1);
            }

            // Create the solr worker
            var solrPageWorker = Solr_Operations_Cache <Legacy_SolrPage> .GetSolrOperations(SolrPageUrl);

            try
            {
                solrPageWorker.Optimize();
            }
            catch (Exception)
            {
                // Do not do anything here.  It may throw an exception when it runs very longs
            }
        }
        /// <summary> Indexes a single digital resource within a SobekCM library </summary>
        /// <param name="SolrDocumentUrl"> URL for the solr/lucene core used for searching for a single document within the library </param>
        /// <param name="SolrPageUrl"> URL for the solr/lucene core used for searching within a single document for matching pages </param>
        /// <param name="Resource"> Digital resource to index</param>
        /// <param name="Include_Text"> Flag indicates whether to look for and include full text </param>
        public void Update_Index(string SolrDocumentUrl, string SolrPageUrl, SobekCM_Item Resource, bool Include_Text)
        {
            // Create the solr workers
            var solrDocumentWorker = Solr_Operations_Cache <Legacy_SolrDocument> .GetSolrOperations(SolrDocumentUrl);

            var solrPageWorker = Solr_Operations_Cache <Legacy_SolrPage> .GetSolrOperations(SolrPageUrl);

            // Get the list of all items in this collection
            List <Legacy_SolrDocument> index_files = new List <Legacy_SolrDocument>();
            List <Legacy_SolrPage>     index_pages = new List <Legacy_SolrPage>();

            // Add this document to the list of documents to index
            index_files.Add(new Legacy_SolrDocument(Resource, Resource.Source_Directory));

            bool document_success  = false;
            int  document_attempts = 0;

            while (!document_success)
            {
                try
                {
                    solrDocumentWorker.Add(index_files);
                    document_success = true;
                }
                catch (Exception)
                {
                    if (document_attempts > 5)
                    {
                        throw;
                    }
                    document_attempts++;
                    Console.WriteLine(@"ERROR {0}", document_attempts);
                    Thread.Sleep(document_attempts * 1000);
                }
            }

            // Add each page to be indexed
            foreach (Legacy_SolrDocument document in index_files)
            {
                index_pages.AddRange(document.Solr_Pages);
            }


            bool page_success  = false;
            int  page_attempts = 0;

            while (!page_success)
            {
                try
                {
                    solrPageWorker.Add(index_pages);
                    page_success = true;
                }
                catch (Exception)
                {
                    if (page_attempts > 5)
                    {
                        throw;
                    }
                    page_attempts++;
                    Thread.Sleep(page_attempts * 1000);
                }
            }

            // Comit the changes to the solr/lucene index
            try
            {
                solrDocumentWorker.Commit();
            }
            catch
            {
                Thread.Sleep(10 * 60 * 1000);
            }

            try
            {
                solrPageWorker.Commit();
            }
            catch
            {
                Thread.Sleep(10 * 60 * 1000);
            }
        }
        /// <summary> Perform an in-document search for pages with matching full-text </summary>
        /// <param name="BibID"> Bibliographic identifier (BibID) for the item to search </param>
        /// <param name="VID"> Volume identifier for the item to search </param>
        /// <param name="Search_Terms"> Terms to search for within the page text </param>
        /// <param name="ResultsPerPage"> Number of results to display per a "page" of results </param>
        /// <param name="ResultsPage"> Which page of results to return ( one-based, so the first page is page number of one )</param>
        /// <param name="Sort_By_Score"> Flag indicates whether to sort the results by relevancy score, rather than the default page order </param>
        /// <returns> Page search result object with all relevant result information </returns>
        public static Legacy_Solr_Page_Results Search_Within_Document(string BibID, string VID, List <string> Search_Terms, int ResultsPerPage, int ResultsPage, bool Sort_By_Score)
        {
            // Ensure page is not erroneously set to zero or negative
            if (ResultsPage <= 0)
            {
                ResultsPage = 1;
            }

            // Create the solr worker to query the page index
            var solrWorker = Solr_Operations_Cache <Legacy_Solr_Page_Result> .GetSolrOperations(Engine_ApplicationCache_Gateway.Settings.Servers.Page_Solr_Legacy_URL);

            // Create the query options
            QueryOptions options = new QueryOptions
            {
                Rows      = ResultsPerPage,
                Start     = (ResultsPage - 1) * ResultsPerPage,
                Fields    = new[] { "pageid", "pagename", "pageorder", "score", "thumbnail" },
                Highlight = new HighlightingParameters {
                    Fields = new[] { "pagetext" },
                },
                ExtraParams = new Dictionary <string, string> {
                    { "hl.useFastVectorHighlighter", "true" }
                }
            };

            // If this is not the default Solr sort (by score) request sort by the page order
            if (!Sort_By_Score)
            {
                options.OrderBy = new[] { new SortOrder("pageorder", Order.ASC) }
            }
            ;

            // Build the query string
            StringBuilder queryStringBuilder = new StringBuilder("(bibid:" + BibID + ")AND(vid:" + VID + ")AND(");
            bool          first_value        = true;

            foreach (string searchTerm in Search_Terms)
            {
                if (searchTerm.Length > 1)
                {
                    // Skip any AND NOT for now
                    if (searchTerm[0] != '-')
                    {
                        // Find the joiner
                        if (first_value)
                        {
                            if (searchTerm.IndexOf(" ") > 0)
                            {
                                if ((searchTerm[0] == '+') || (searchTerm[0] == '=') || (searchTerm[0] == '-'))
                                {
                                    queryStringBuilder.Append("(pagetext:\"" + searchTerm.Substring(1).Replace(":", "") + "\")");
                                }
                                else
                                {
                                    queryStringBuilder.Append("(pagetext:\"" + searchTerm.Replace(":", "") + "\")");
                                }
                            }
                            else
                            {
                                if ((searchTerm[0] == '+') || (searchTerm[0] == '=') || (searchTerm[0] == '-'))
                                {
                                    queryStringBuilder.Append("(pagetext:" + searchTerm.Substring(1).Replace(":", "") + ")");
                                }
                                else
                                {
                                    queryStringBuilder.Append("(pagetext:" + searchTerm.Replace(":", "") + ")");
                                }
                            }
                            first_value = false;
                        }
                        else
                        {
                            if ((searchTerm[0] == '+') || (searchTerm[0] == '=') || (searchTerm[0] == '-'))
                            {
                                queryStringBuilder.Append(searchTerm[0] == '=' ? " OR " : " AND ");

                                if (searchTerm.IndexOf(" ") > 0)
                                {
                                    queryStringBuilder.Append("(pagetext:\"" + searchTerm.Substring(1).Replace(":", "") + "\")");
                                }
                                else
                                {
                                    queryStringBuilder.Append("(pagetext:" + searchTerm.Substring(1).Replace(":", "") + ")");
                                }
                            }
                            else
                            {
                                if (searchTerm.IndexOf(" ") > 0)
                                {
                                    queryStringBuilder.Append(" AND (pagetext:\"" + searchTerm.Replace(":", "") + "\")");
                                }
                                else
                                {
                                    queryStringBuilder.Append(" AND (pagetext:" + searchTerm.Replace(":", "") + ")");
                                }
                            }
                        }
                    }
                }
            }
            queryStringBuilder.Append(")");


            // Perform this search
            SolrQueryResults <Legacy_Solr_Page_Result> results = solrWorker.Query(queryStringBuilder.ToString(), options);

            // Create the results object to pass back out
            var searchResults = new Legacy_Solr_Page_Results
            {
                QueryTime     = results.Header.QTime,
                TotalResults  = results.NumFound,
                Query         = queryStringBuilder.ToString(),
                Sort_By_Score = Sort_By_Score,
                Page_Number   = ResultsPage
            };

            // Pass all the results into the List and add the highlighted text to each result as well
            foreach (Legacy_Solr_Page_Result thisResult in results)
            {
                // Add the highlight snipper
                if ((results.Highlights.ContainsKey(thisResult.PageID)) && (results.Highlights[thisResult.PageID].Count > 0) && (results.Highlights[thisResult.PageID].ElementAt(0).Value.Count > 0))
                {
                    thisResult.Snippet = results.Highlights[thisResult.PageID].ElementAt(0).Value.ElementAt(0);
                }

                // Add this results
                searchResults.Add_Result(thisResult);
            }

            return(searchResults);
        }

        #endregion
    }
        /// <summary> Perform an search for documents with matching parameters </summary>
        /// <param name="AggregationCode"> Aggregation code within which to search </param>
        /// <param name="Terms"> List of the search terms </param>
        /// <param name="Web_Fields"> List of the web fields associate with the search terms </param>
        /// <param name="ResultsPerPage"> Number of results to display per a "page" of results </param>
        /// <param name="Page_Number"> Which page of results to return ( one-based, so the first page is page number of one )</param>
        /// <param name="Sort"> Sort to apply before returning the results of the search </param>
        /// <param name="Need_Search_Statistics"> Flag indicates if the search statistics are needed </param>
        /// <param name="Tracer"> Trace object keeps a list of each method executed and important milestones in rendering </param>
        /// <param name="Complete_Result_Set_Info"> [OUT] Information about the entire set of results </param>
        /// <param name="Paged_Results"> [OUT] List of search results for the requested page of results </param>
        /// <returns> Page search result object with all relevant result information </returns>
        public static bool Search(string AggregationCode, List <string> Terms, List <string> Web_Fields, int ResultsPerPage, int Page_Number, ushort Sort, bool Need_Search_Statistics, Custom_Tracer Tracer, out Search_Results_Statistics Complete_Result_Set_Info, out List <iSearch_Title_Result> Paged_Results)
        {
            if (Tracer != null)
            {
                Tracer.Add_Trace("Legacy_Solr_Documents_Searcher.Search", "Build the Solr query");
            }

            // Step through all the terms and fields
            StringBuilder queryStringBuilder = new StringBuilder();

            for (int i = 0; i < Math.Min(Terms.Count, Web_Fields.Count); i++)
            {
                string web_field  = Web_Fields[i];
                string searchTerm = Terms[i];
                string solr_field;

                if (i == 0)
                {
                    // Skip any joiner for the very first field indicated
                    if ((web_field[0] == '+') || (web_field[0] == '=') || (web_field[0] == '-'))
                    {
                        web_field = web_field.Substring(1);
                    }

                    // Try to get the solr field
                    if (web_field == "TX")
                    {
                        solr_field = "fulltext:";
                    }
                    else
                    {
                        Metadata_Search_Field field = Engine_ApplicationCache_Gateway.Settings.Metadata_Search_Field_By_Code(web_field.ToUpper());
                        if (field != null)
                        {
                            solr_field = field.Legacy_Solr_Code + ":";
                        }
                        else
                        {
                            solr_field = String.Empty;
                        }
                    }

                    // Add the solr search string
                    if (searchTerm.IndexOf(" ") > 0)
                    {
                        queryStringBuilder.Append("(" + solr_field + "\"" + searchTerm.Replace(":", "") + "\")");
                    }
                    else
                    {
                        queryStringBuilder.Append("(" + solr_field + searchTerm.Replace(":", "") + ")");
                    }
                }
                else
                {
                    // Add the joiner for this subsequent terms
                    if ((web_field[0] == '+') || (web_field[0] == '=') || (web_field[0] == '-'))
                    {
                        switch (web_field[0])
                        {
                        case '=':
                            queryStringBuilder.Append(" OR ");
                            break;

                        case '+':
                            queryStringBuilder.Append(" AND ");
                            break;

                        case '-':
                            queryStringBuilder.Append(" NOT ");
                            break;

                        default:
                            queryStringBuilder.Append(" AND ");
                            break;
                        }
                        web_field = web_field.Substring(1);
                    }
                    else
                    {
                        queryStringBuilder.Append(" AND ");
                    }

                    // Try to get the solr field
                    if (web_field == "TX")
                    {
                        solr_field = "fulltext:";
                    }
                    else
                    {
                        Metadata_Search_Field field = Engine_ApplicationCache_Gateway.Settings.Metadata_Search_Field_By_Code(web_field.ToUpper());
                        if (field != null)
                        {
                            solr_field = field.Legacy_Solr_Code + ":";
                        }
                        else
                        {
                            solr_field = String.Empty;
                        }
                    }

                    // Add the solr search string
                    if (searchTerm.IndexOf(" ") > 0)
                    {
                        queryStringBuilder.Append("(" + solr_field + "\"" + searchTerm.Replace(":", "") + "\")");
                    }
                    else
                    {
                        queryStringBuilder.Append("(" + solr_field + searchTerm.Replace(":", "") + ")");
                    }
                }
            }

            if (Tracer != null)
            {
                Tracer.Add_Trace("Legacy_Solr_Documents_Searcher.Search", "Perform the search");
            }

            // Get the query string value
            string queryString = queryStringBuilder.ToString();

            // Set output initially to null
            Paged_Results            = new List <iSearch_Title_Result>();
            Complete_Result_Set_Info = null;

            try
            {
                // Ensure page is not erroneously set to zero or negative
                if (Page_Number <= 0)
                {
                    Page_Number = 1;
                }

                // Create the solr worker to query the document index
                var solrWorker = Solr_Operations_Cache <Legacy_Solr_Document_Result> .GetSolrOperations(Engine_ApplicationCache_Gateway.Settings.Servers.Document_Solr_Legacy_URL);

                // Create the query options
                QueryOptions options = new QueryOptions
                {
                    Rows      = ResultsPerPage,
                    Start     = (Page_Number - 1) * ResultsPerPage,
                    Fields    = new[] { "did", "score", "url", "aleph", "donor", "edition", "format", "holdinglocation", "sourceinstitution", "maintitle", "materialtype", "oclc", "pubdate_display", "author_display", "publisher_display", "mainthumbnail" },
                    Highlight = new HighlightingParameters {
                        Fields = new[] { "fulltext" },
                    },
                    ExtraParams = new Dictionary <string, string> {
                        { "hl.useFastVectorHighlighter", "true" }
                    }
                };

                // Set the sort value
                if (Sort != 0)
                {
                    options.OrderBy.Clear();
                    switch (Sort)
                    {
                    case 1:
                        options.OrderBy.Add(new SortOrder("maintitle_sort"));
                        break;

                    case 2:
                        options.OrderBy.Add(new SortOrder("bibid", Order.ASC));
                        break;

                    case 3:
                        options.OrderBy.Add(new SortOrder("bibid", Order.DESC));
                        break;

                    case 10:
                        options.OrderBy.Add(new SortOrder("pubdate", Order.ASC));
                        break;

                    case 11:
                        options.OrderBy.Add(new SortOrder("pubdate", Order.DESC));
                        break;
                    }
                }

                // If there was an aggregation code included, put that at the beginning of the search
                if ((AggregationCode.Length > 0) && (AggregationCode.ToUpper() != "ALL"))
                {
                    queryString = "(aggregation_code:" + AggregationCode.ToUpper() + ")AND(" + queryString + ")";
                }

                // Perform this search
                SolrQueryResults <Legacy_Solr_Document_Result> results = solrWorker.Query(queryString, options);

                // Create the search statistcs
                List <string> metadataLabels = new List <string> {
                    "Author", "Publisher", "Format", "Edition", "Institution", "Donor"
                };

                Complete_Result_Set_Info = new Search_Results_Statistics(metadataLabels)
                {
                    Total_Titles = results.NumFound,
                    Total_Items  = results.NumFound,
                    QueryTime    = results.Header.QTime
                };

                // Pass all the results into the List and add the highlighted text to each result as well
                foreach (Legacy_Solr_Document_Result thisResult in results)
                {
                    // Add the highlight snipper
                    if ((results.Highlights.ContainsKey(thisResult.DID)) && (results.Highlights[thisResult.DID].Count > 0) && (results.Highlights[thisResult.DID].ElementAt(0).Value.Count > 0))
                    {
                        thisResult.Snippet = results.Highlights[thisResult.DID].ElementAt(0).Value.ElementAt(0);
                    }

                    // Add this results
                    Paged_Results.Add(thisResult);
                }

                return(true);
            }
            catch
            {
                return(false);
            }
        }
예제 #8
0
        /// <summary> Run a solr query against the solr document index </summary>
        /// <param name="QueryString"> Solr query string </param>
        /// <param name="SearchOptions"> Options related to this search, like the page, results per page, facets, fields, etc.. </param>
        /// <param name="UserMembership"> User-specific membership information, related to a search, which can be used to determine which items this user can discover</param>
        /// <param name="Tracer"> Trace object keeps a list of each method executed and important milestones in rendering </param>
        /// <param name="Complete_Result_Set_Info"> [OUT] Information about the entire set of results </param>
        /// <param name="Paged_Results"> [OUT] List of search results for the requested page of results </param>
        /// <returns> Page search result object with all relevant result information </returns>
        public static bool Run_Query(string QueryString, Search_Options_Info SearchOptions, Search_User_Membership_Info UserMembership, Custom_Tracer Tracer, out Search_Results_Statistics Complete_Result_Set_Info, out List <iSearch_Title_Result> Paged_Results)
        {
            // If the query string is empty, then set it back to *:*
            if (QueryString.Trim().Length == 0)
            {
                QueryString = "*:*";
            }

            // Set output initially to null
            Paged_Results            = new List <iSearch_Title_Result>();
            Complete_Result_Set_Info = null;

            try
            {
                // Ensure page is not erroneously set to zero or negative
                int pageNumber = SearchOptions.Page;
                if (pageNumber <= 0)
                {
                    pageNumber = 1;
                }

                // Get and clean the solr document url
                string solrDocumentUrl = Engine_ApplicationCache_Gateway.Settings.Servers.Document_Solr_Index_URL;
                if ((!String.IsNullOrEmpty(solrDocumentUrl)) && (solrDocumentUrl[solrDocumentUrl.Length - 1] == '/'))
                {
                    solrDocumentUrl = solrDocumentUrl.Substring(0, solrDocumentUrl.Length - 1);
                }

                // Create the solr worker to query the document index
                var solrWorker = Solr_Operations_Cache <v5_SolrDocument> .GetSolrOperations(solrDocumentUrl);

                // Get the list of fields
                List <string> fields = new List <string> {
                    "did", "mainthumb", "title"
                };
                fields.AddRange(SearchOptions.Fields.Select(MetadataField => MetadataField.SolrCode));

                // Create the query options
                QueryOptions options = new QueryOptions
                {
                    Rows   = SearchOptions.ResultsPerPage,
                    Start  = (pageNumber - 1) * SearchOptions.ResultsPerPage,
                    Fields = fields
                };

                // Was there full text search in that?
                if ((QueryString.Contains("(fulltext:")) && (SearchOptions.IncludeFullTextSnippets))
                {
                    options.Highlight = new HighlightingParameters {
                        Fields = new[] { "fulltext" }, Fragsize = 255
                    };
                    options.ExtraParams = new Dictionary <string, string> {
                        { "hl.useFastVectorHighlighter", "true" }, { "wt", "xml" }
                    };
                }
                else
                {
                    // We still need to instruct SOLR to return the results as XML for solr to parse it
                    options.ExtraParams = new KeyValuePair <string, string>[] { new KeyValuePair <string, string>("wt", "xml") };
                }

                // If the search stats are needed, let's get the facets
                if ((SearchOptions.Facets != null) && (SearchOptions.Facets.Count > 0))
                {
                    // Create the query facters
                    options.Facet = new FacetParameters();
                    foreach (Complete_Item_Aggregation_Metadata_Type facet in SearchOptions.Facets)
                    {
                        options.Facet.Queries.Add(new SolrFacetFieldQuery(facet.SolrCode)
                        {
                            MinCount = 1, Limit = 100
                        });
                    }
                }

                // Set the sort value
                if (SearchOptions.Sort != 0)
                {
                    options.OrderBy.Clear();
                    switch (SearchOptions.Sort)
                    {
                    case 1:
                        options.OrderBy.Add(new SortOrder("title.sort", Order.ASC));
                        break;

                    case 2:
                        options.OrderBy.Add(new SortOrder("bibid", Order.ASC));
                        break;

                    case 3:
                        options.OrderBy.Add(new SortOrder("bibid", Order.DESC));
                        break;

                    case 10:
                        options.OrderBy.Add(new SortOrder("date.gregorian", Order.ASC));
                        break;

                    case 11:
                        options.OrderBy.Add(new SortOrder("date.gregorian", Order.DESC));
                        break;

                    case 12:
                        options.OrderBy.Add(new SortOrder("timeline_date", Order.ASC));

                        // If sorting by this, only get records with timeline date
                        QueryString = "(" + QueryString + ") AND timeline_date:[* TO *]";
                        break;
                    }
                }

                // Should this be grouped?
                bool grouped_results = false;
                if ((SearchOptions.GroupItemsByTitle) && (SearchOptions.Sort < 10) && (QueryString.IndexOf("fulltext") < 0))
                {
                    if (Tracer != null)
                    {
                        Tracer.Add_Trace("v5_Solr_Documents_Searcher.Run_Query", "Grouping search request by bibid");
                    }

                    grouped_results = true;

                    GroupingParameters groupingParams = new GroupingParameters
                    {
                        Fields = new[] { "bibid" },

                        Format = GroupingFormat.Grouped,

                        Limit = 10,

                        Ngroups = true
                    };

                    options.Grouping = groupingParams;
                }

                // Log the search term
                if (Tracer != null)
                {
                    Tracer.Add_Trace("v5_Solr_Documents_Searcher.Run_Query", "Solr Query: " + QueryString);
                }

                if (Tracer != null)
                {
                    Tracer.Add_Trace("v5_Solr_Documents_Searcher.Run_Query", "Perform the search");
                }

                // Perform this search
                SolrQueryResults <v5_SolrDocument> results = solrWorker.Query(QueryString, options);


                if (Tracer != null)
                {
                    Tracer.Add_Trace("v5_Solr_Documents_Searcher.Run_Query", "Build the results object");
                }

                // Create the search statistcs (this part assumes no grouping, and then we fix the count shortly)
                List <string> metadataLabels = SearchOptions.Fields.Select(MetadataType => MetadataType.DisplayTerm).ToList();
                Complete_Result_Set_Info = new Search_Results_Statistics(metadataLabels)
                {
                    Total_Titles = results.NumFound,
                    Total_Items  = results.NumFound,
                    QueryTime    = results.Header.QTime
                };

                // If the search stats were needed, get the facets out
                if ((SearchOptions.Facets != null) && (SearchOptions.Facets.Count > 0))
                {
                    // Copy over all the facets
                    foreach (Complete_Item_Aggregation_Metadata_Type facetTerm in SearchOptions.Facets)
                    {
                        // Create the collection and and assifn the metadata type id
                        Search_Facet_Collection thisCollection = new Search_Facet_Collection(facetTerm.ID);

                        // Add each value
                        foreach (var facet in results.FacetFields[facetTerm.SolrCode])
                        {
                            thisCollection.Facets.Add(new Search_Facet(facet.Key, facet.Value));
                        }

                        // If there was an id and facets added, save this to the search statistics
                        if ((thisCollection.MetadataTypeID > 0) && (thisCollection.Facets.Count > 0))
                        {
                            Complete_Result_Set_Info.Facet_Collections.Add(thisCollection);
                        }
                    }
                }

                // Build the results mapper object
                v5_SolrDocument_Results_Mapper mapper = new v5_SolrDocument_Results_Mapper();

                // Build the results differently, depending on whether they were grouped or not
                if (grouped_results)
                {
                    // Get the grouped results (only grouped by bibid)
                    GroupedResults <v5_SolrDocument> title_groupings = results.Grouping["bibid"];

                    // Now step through each group (i.e., titles/bibs) in the groups
                    foreach (Group <v5_SolrDocument> grouping in title_groupings.Groups)
                    {
                        // Convert the grouping to the new result
                        v5_Solr_Title_Result newResult = mapper.Map_To_Result(grouping, SearchOptions.Fields);

                        Paged_Results.Add(newResult);
                    }

                    // Now, fix the stats as well
                    Complete_Result_Set_Info.Total_Items  = title_groupings.Matches;
                    Complete_Result_Set_Info.Total_Titles = title_groupings.Ngroups.Value;
                }
                else
                {
                    // Pass all the results into the List and add the highlighted text to each result as well
                    foreach (v5_SolrDocument thisResult in results)
                    {
                        // Convert to the new result
                        v5_Solr_Title_Result newResult = mapper.Map_To_Result(thisResult, SearchOptions.Fields);

                        // Add the highlight snippet, if applicable
                        if ((results.Highlights != null) && (results.Highlights.ContainsKey(thisResult.DID)) && (results.Highlights[thisResult.DID].Count > 0) && (results.Highlights[thisResult.DID].ElementAt(0).Value.Count > 0))
                        {
                            newResult.Snippet = results.Highlights[thisResult.DID].ElementAt(0).Value.ElementAt(0);
                        }

                        Paged_Results.Add(newResult);
                    }
                }

                return(true);
            }
            catch (Exception ee)
            {
                return(false);
            }
        }
        /// <summary> Indexes a single digital resource within a SobekCM library </summary>
        /// <param name="SolrDocumentUrl"> URL for the solr/lucene core used for searching for a single document within the library </param>
        /// <param name="SolrPageUrl"> URL for the solr/lucene core used for searching within a single document for matching pages </param>
        /// <param name="Resource"> Digital resource to index</param>
        /// <param name="Include_Text"> Flag indicates whether to look for and include full text </param>
        public void Update_Index(string SolrDocumentUrl, string SolrPageUrl, SobekCM_Item Resource, bool Include_Text)
        {
            // Get rid of trailling '/' in solr document url
            SolrDocumentUrl = SolrDocumentUrl.Trim();
            if ((!String.IsNullOrEmpty(SolrDocumentUrl)) && (SolrDocumentUrl[SolrDocumentUrl.Length - 1] == '/'))
            {
                SolrDocumentUrl = SolrDocumentUrl.Substring(0, SolrDocumentUrl.Length - 1);
            }

            // Get rid of trailling '/' in solr page url
            SolrPageUrl = SolrPageUrl.Trim();
            if ((!String.IsNullOrEmpty(SolrPageUrl)) && (SolrPageUrl[SolrPageUrl.Length - 1] == '/'))
            {
                SolrPageUrl = SolrPageUrl.Substring(0, SolrPageUrl.Length - 1);
            }


            // Create the solr workers
            var solrDocumentWorker = Solr_Operations_Cache <v5_SolrDocument> .GetSolrOperations(SolrDocumentUrl);

            var solrPageWorker = Solr_Operations_Cache <Legacy_SolrPage> .GetSolrOperations(SolrPageUrl);

            // Get the list of all items in this collection
            List <v5_SolrDocument> index_files = new List <v5_SolrDocument>();
            List <Legacy_SolrPage> index_pages = new List <Legacy_SolrPage>();

            // Add this document to the list of documents to index
            v5_SolrDocument_Builder builder      = new v5_SolrDocument_Builder();
            v5_SolrDocument         solrDocument = builder.Build_Solr_Document(Resource, Resource.Source_Directory);

            index_files.Add(solrDocument);

            bool document_success  = false;
            int  document_attempts = 0;

            while (!document_success)
            {
                try
                {
                    solrDocumentWorker.AddRange(index_files);
                    document_success = true;
                }
                catch (Exception ee)
                {
                    if (document_attempts > 5)
                    {
                        throw;
                    }
                    document_attempts++;
                    Console.WriteLine(@"ERROR {0}", document_attempts);
                    Thread.Sleep(document_attempts * 1000);
                }
            }

            // Add each page to be indexed
            foreach (v5_SolrDocument document in index_files)
            {
                index_pages.AddRange(document.Solr_Pages);
            }


            bool page_success  = false;
            int  page_attempts = 0;

            while (!page_success)
            {
                try
                {
                    solrPageWorker.Add(index_pages);
                    page_success = true;
                }
                catch (Exception ee)
                {
                    if (page_attempts > 5)
                    {
                        throw;
                    }
                    page_attempts++;
                    Thread.Sleep(page_attempts * 1000);
                }
            }

            // Comit the changes to the solr/lucene index
            try
            {
                solrDocumentWorker.Commit();
            }
            catch (Exception ee)
            {
                Thread.Sleep(10 * 60 * 1000);
            }

            try
            {
                solrPageWorker.Commit();
            }
            catch (Exception ee)
            {
                Thread.Sleep(10 * 60 * 1000);
            }
        }