Friday, August 5, 2016

Type ahead for Search Suggestions in SharePoint 2013

 Solution: Get top 5 results searching only on title field. Other parameters can be added as well
                Query term is what the user has entered with a wildcard appended
  

Pr-requites:
1) There should be a Search Center configured in the site Collection.
2) Create a Result Source to get all results and insert that Source id inside root level Property bag ( Eg:
<Key>SearchSuggestionsResultSource : <Value> 8f23f3c1-de7e-4c9b-bd14-de43cd07a3c9
)
Development Steps:

I could add this functionality to the existing search box on the search center. The search box has three settings for search as you type suggestions. Suggestions based on what everyone searches which is recorded over time (or you can manually add suggestions), suggestions matching people names, and personal favorites – which are searches you perform often.
The search suggestions functionality in SharePoint 2013 is provided by ajaxtoolkit.js. In order to extend the existing functionality I had to override the _update function of the AjaxControlToolkit.AutoCompleteBehavior.prototype which is responsible for the search as you type functionality of the search box.


 Config with Master Page :
1) Design Master -> Edit Page Layouts - > Create Page Layout with Your Master Page -> Click on that and go to the Page -> Click on Snippets
2) In Snippets Gallery select the Web Parts and click on Search Box
3) Change your changes inside Properties for search
4) In our requirement checked Show people name suggestions in Query Suggestions and update it.
5) Now you can copy Clipboard coding (in HTML Snippet) and insert that inside your html master page layout created early by downloading it from master page in settings.
6) Then upload that and published.
7) Now you can copy the search box content into .aspx page of that html master page and published.
8) Get that content and paste that content inside your .master page search box section.
9) Add JS link inside the master page
<script type="text/javascript" src="../Style%20Library/Controller/typeAhead.js">

</script>

Normal Steps in Development:

1.       Drop a content editor web part on the page and give the script link for js file or you can directly copy paste the code to script editor.
function Override() {
    // Keep a copy of the original function
    AjaxControlToolkit.AutoCompleteBehavior.prototype._update2 = AjaxControlToolkit.AutoCompleteBehavior.prototype._update;

    // register the searchOnSuccess on the same prototype object in order for the update2 function to keep the
    // context with all variables
    AjaxControlToolkit.AutoCompleteBehavior.prototype.searchOnSuccess = function (data, prefixText, completionItems, cacheResults) {
        var results = data.d.query.PrimaryQueryResult.RelevantResults.Table.Rows.results;

        var names = [];
        for (var i = 0; i < results.length; i++) {
            var title = results[i].Cells.results[3].Value;
            // Add highlighting of the search term
            var idx = title.toLowerCase().indexOf(prefixText.toLowerCase());
            if (idx >= 0) {
                var hhtitle = title.substr(0, idx) + "<b>" + title.substr(idx, prefixText.length) + "</b>" + title.substr(idx + prefixText.length);
                names.push(hhtitle);
            } else {
                names.push(title); // fallback if indexof fails
            }
            /*              href = results[i].Cells.results[6].Value; */
        }
        // put our results in the people name container as we're not using it on our page
        completionItems.set_peopleNames(names);
        // call the original update function which renders out the results
        this._update2(prefixText, completionItems, cacheResults);
    };

    // Register an overload update function which executes a real search    
    AjaxControlToolkit.AutoCompleteBehavior.prototype._update = function (prefixText, completionItems, cacheResults) {
        var context = this;
        var root,sourceID = "";
        //var sourceID = localStorage.getItem("SearchSuggestionsResultSource");
        //alert(sourceID);
        $.ajax({
            url: _spPageContextInfo.webAbsoluteUrl + "/_api/web/allProperties?$select=RootSiteCollectionUrl",
            method: "GET",
            headers: { "Accept": "application/json; odata=verbose" },
            success: function (data) {
                root = data.d.RootSiteCollectionUrl;

            },
            error: function (data) {
                console.log(JSON.stringify(data));
            }
        }).done(function () {
            $.ajax({
                url: root + "/_api/web/allProperties?$select=SearchSuggestionsResultSource",
                method: "GET",
                headers: { "Accept": "application/json; odata=verbose" },
                success: function (data) {
                    sourceID = data.d.NYLKMPSearchSuggestionsResultSource;

                },
                error: function (data) {
                    console.log(JSON.stringify(data));
                }

            }).done(function () {
                $.ajax(
                    {
                        // Get top 5 results searching only on title field. Other paramaters can be added as well
                        // Query term is what the user has entered with a wildcard appended            
                       
                        url: _spPageContextInfo.webAbsoluteUrl + "/_api/search/query?rowlimit=5&querytext='title:\"" + prefixText + "*\"'&sourceid='" + sourceID + "'",

                        method: "GET",
                        headers: {
                            "accept": "application/json;odata=verbose;charset=utf-8",
                        },
                        success: function (data) { context.searchOnSuccess(data, prefixText, completionItems, cacheResults); },
                        error: onError
                    });
            });
        });
        function onError(err) {
            //alert(JSON.stringify(err));
            console.log(JSON.stringify(err));
        }
    }

}


// Replace url to your own jquery path
ExecuteOrDelayUntilScriptLoaded(Override, 'ajaxtoolkit.js');

 
2.       Edit Search Result web part and checked show people name in query suggestions.
 

Saturday, May 21, 2016

Sort Search Results in SharePoint 2013


One of the requirements for the project was to roll up data from a list that’s sorted by Name, Relevance  and Last Date modified in descending order.

In previous versions of SharePoint, the out-of-the-box search results provided links to show results by relevance or modified date. Now, with SharePoint 2013, the results may be sorted by any managed property but there are a few preset values. However, by default, the sort option is not enabled. So to allow your users to sort search results, follow these simple steps:

1) Edit one of the results pages in your search center site and Edit the Search Results web part:



2) To add the JSON go into the search results web part properties, expand the “Settings” toggle and enable the “Show sort dropdown” option. We can get rid of all the predefined sort orders and insert our own :

 
Our Query  :
[{"name":"Relevance","sorts":[]},
{"name":"Name","sorts":[{"p":"DocTitle","d":1}]},
{"name":"Date Modified","sorts":[{"p":"Write","d":1}]}]

The sort options are controlled by the JSON in the Available sort orders text box. You may modify this to add or remove sort options. Feel free to choose from any of the 600+ managed properties available out-of-the-box.

What does the JSON mean?

eg : Sort according to Name and Location
Let’s format the JSON to get an understanding of what’s going on here. 



The “name” property is the display name that you will see in the search drop down. Even though we’re not displaying the search drop down in our Web Part you can still give it a meaningful name.
The “sorts” property contains our sort order for the search results. The “p” is the managed property name and the “d” defines whether descending order is true or false (1 is descending and 0 is ascending).

3) Click OK in the toolpane and check-in the changes of the page.

4) Perform a search. A drop-down appears above the results:



How To add a managed property

1.      Verify that the user account that is performing this procedure is an administrator for the Search service application.
2.      In Central Administration, in the Application Management section, click Manage service applications.
3.      Click the Search service application.
4.      On the Search Administration page, in the Quick Launch, under Queries and Results, click Search Schema.
5.      On the Managed Properties page, click New Managed Property.
6.      On the New Managed Property page, in the Property name box in the Name and description section, enter the name of the new managed property. You can also enter a description.
7.      In the Type section, select one of the following options for the property:
o    Text
o    Integer
o    Decimal
o    Date and Time
o    Yes/No
o    Double precision float
o    Binary
8.      In the Main characteristics section, select one or several of the following:
o    Searchable
o    Advanced Searchable Settings (optional, if Searchable is selected)
o    Queryable
o    Retrievable
o    Allow multiple values
o    Refinable
o    Sortable
o    Alias
o    Token Normalization
o    Complete Matching
Important :
If you want to be able to use this managed property as a refiner, you must select both Refinable and Queryable.
If you want to use this managed property for sort, you must select Sortable 

9.      In the Mappings to crawled properties section, click Add a mapping.
10.  On the Crawled property selection page, select a crawled property to map to the managed property and then click OK. Repeat this step to map more crawled properties.
11.  On the New Managed Property page, in the Mappings to crawled properties section, specify if you want to include:
o    All content from all crawled properties mapped to this managed property
o    Content from the first crawled property that contains a value and, optionally, in which order.
12.  In the Company name extraction section, you can optionally select the check box to enable company name extraction.
13.  In the Custom entity extraction section, you can optionally select the check box to enable custom entity extraction. See Create and deploy custom entity extractors in SharePoint Server 2013 for the procedures.
14.  Click OK.


To edit a managed property

1.      Verify that the user account that is performing this procedure is an administrator for the Search service application.
2.      In Central Administration, in the Application Management section, click Manage service applications.
3.      Click the Search service application.
4.      On the Search Administration page, in the Quick Launch, under Queries and Results, click Search Schema.
5.      On the Managed Properties page, find the managed property that you want to edit, or enter its name in the Filter box.
6.      Point to the managed property that you want to edit, click the arrow, and then click Edit/Map property.
7.      On the Edit Managed Property page, edit the settings and then click OK.