all files / src/ sputils.search.js

82.93% Statements 34/41
57.14% Branches 8/14
100% Functions 10/10
82.93% Lines 34/41
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            
(function () {
  /**
   * @private
   * @const search.POST_URL_PATH the sub-path used for POST requests */
  var POST_URL_PATH = '_api/search/postquery';
 
  /**
   * @private
   * @const search.GET_URL_PATH the sub-path used for GET requests */
  var GET_URL_PATH = '_api/search/query';
 
  /**
   * @private
   * @returns {object}
   * __metadata for use in POST requests' bodies to search API */
  var __metadata = function () {
    return {
      __metadata: {
        type: 'Microsoft.Office.Server.Search.REST.SearchRequest'
      }
    };
  };
 
  /**
   * An example search configuration
   * @function sputils.search.searchCfgExample
   * @see {@link https://msdn.microsoft.com/en-us/library/office/jj163876.aspx}
   * @returns {object} a new object instance of a SearchConfigurationExample
   */
  var searchCfgExample = function () {
    return {
      // A string that contains the text for the search query.
      'Querytext': 'sharepoint',
      // A string that contains the text that replaces the query text, as part
      // of a query transform.
      'Querytemplate': '{searchterms} Author:johndoe',
      // A 'Boolean' value that specifies whether the result tables that are
      // returned for the result block are mixed with the result tables that
      // are  returned for the original query.
      // true to mix the ResultTables; otherwise, false. The default value
      // is true. Change this value only if you want to provide your own
      // interleaving implementation.
      'EnableInterleaving': 'True',
      // The result source ID to use for executing the search query.
      'SourceId': '8413cd39-2156-4e00-b54d-11efd9abdb89',
      // The ID of the ranking model to use for the query.
      'RankingModelId': 'CustomRankingModelID',
      // The first row that is included in the search results that are
      //  returned. You use this parameter when you want to implement
      // paging for search results.
      'StartRow': '10',
      // The maximum number of rows overall that are returned in the search
      //  results. Compared to RowsPerPage, RowLimit is the maximum number
      //  of rows returned overall.
      'RowLimit': '30',
      // The maximum number of rows to return per page. Compared to RowLimit,
      // RowsPerPage refers to the maximum number of rows to return per
      // page, and is used primarily when you want to implement paging for
      // search results.
      'RowsPerPage': '10',
      // The managed properties to return in the search results. To return
      // a managed property, set the property's retrievable flag to true
      //  in the search schema.
      'SelectProperties': {
        'results': [
          'Title',
          'Author'
        ]
      },
      // The locale ID (LCID) for the query.
      // https://msdn.microsoft.com/en-us/goglobal/bb964664.aspx
      'Culture': '1044',
      // The set of refinement filters used when issuing a refinement
      // query. For GET requests, the RefinementFilters parameter is
      // specified as an FQL filter. For POST requests, the RefinementFilters
      // parameter is specified as an array of FQL filters.
      'RefinementFilters': {
        'results': ['fileExtension:equals("docx")']
      },
      // The set of refiners to return in a search result.
      'Refiners': {
        'results': ['author,size']
      },
      // The additional query terms to append to the query.
      'HiddenConstraints': 'developer',
      // The list of properties by which the search results are ordered.
      'SortList': {
        'results': [
          {
            'Property': 'Created',
            'Direction': '0'
          },
          {
            'Property': 'FileExtension',
            'Direction': '1'
          }
        ]
      },
      // A Boolean value that specifies whether stemming is enabled.
      'EnableStemming': 'False',
      // A Boolean value that specifies whether duplicate items are removed
      // from the results.
      'TrimDuplicates': 'False',
      // The amount of time in milliseconds before the query request times
      // out. The default value is 30000.
      'Timeout': '60000',
      // A Boolean value that specifies whether the exact terms in the search
      // query are used to find matches, or if nicknames are used also.
      'EnableNicknames': 'True',
      'EnablePhonetic': 'True',
      'EnableFQL':'True',
      'BypassResultTypes': 'true',
      'ProcessBestBets': 'true',
      'ClientType':'custom',
      'PersonalizationData': '<GUID>',
      'ResultURL': 'http://server/site/resultspage.aspx',
      'QueryTag': 'tag1;tag2',
      'Properties': {
        'results': [
          {
            'Name': 'sampleBooleanProperty',
            'Value': {
              'BoolVal': 'True',
              // QueryPropertyValueType specifies the type for the property;
              // each type has a specific index value.
              // https://msdn.microsoft.com/en-us/library/office/microsoft.office.server.search.query.querypropertyvaluetype.aspx
              'QueryPropertyValueTypeIndex': 3
            }
          },
          {
            'Name': 'sampleIntProperty',
            'Value': {
              'IntVal': '1234',
              'QueryPropertyValueTypeIndex': 2
            }
          }
        ]
      },
      'EnableQueryRules': 'False' ,
      'ReorderingRules':  {
        'results': [
          {
            'MatchValue': '<someValue>',
            'Boost': '10',
            'MatchType': '0'
          }
        ]
      },
      'ProcessPersonalFavorites': 'false',
      'QueryTemplatePropertiesUrl': 'spfile://webroot/queryparametertemplate.xml',
      'HitHighlihtedMultivaluePropertyLimit': '2',
      'CollapseSpecification': 'Author:1 ContentType:2',
      'EnableSorting': 'false',
      'GenerateBlockRankLog': 'true',
      'UILanguage': '1044',
      'DesiredSnippetLength': '80',
      'MaxSnippetLength': '100' ,
      'Summarylength': '150'
    };
  };
 
  var ensureEndsWithSlash = function (str) {
    var SLASH = '/';
    var lastIsSlash = (str || '').slice(-1)[0] === SLASH;
    Eif (!lastIsSlash) {
      return str + SLASH;
    }
 
    return str;
  };
 
  /**
   * Make a search request with a POST method. Useful if complex data needs
   * to be sent to the server.
   * <pre>
   * Use POST requests in the following scenarios:
   * - When you'll exceed the URL length restriction with a GET request.
   * - When you can't specify the query parameters in a simple URL.
   *   For example, if you have to pass parameter values that contain
   *   a complex type array, or comma-separated strings, you have more
   *   flexibility when constructing the POST request.
   * - When you use the ReorderingRules parameter because it is supported only with POST requests.
   * </pre>
   * @function sputils.search.postSearch
   * @param {object} cfg the search configuration.
   * @see sputils.search.searchCfgExample or SharePoint Search Query Tool
   * @param {string} [webUrl] the url of the web to use as the context.
   * @returns {Promise<object>} the search result
   * @example
   * sputils.search.postSearch({Querytext: 'ContentType:0x01*'})
   *   .then(function (result) { console.log(result) });
   */
  var postSearch = function (cfg, webUrl) {
    var url = webUrl || _spPageContextInfo.siteServerRelativeUrl;
    var data = {
      request: fjs.assign(cfg, __metadata())
    };
 
    return sputils.rest.post(
      ensureEndsWithSlash(url) + POST_URL_PATH,
      data)
      .then(function unwrap(data) {
        return data.d.postquery;
      });
  };
 
  /**
   * @ignore
   * @summary
   * checks an object returned from the search API to be a specific type.
   */
  var checkType = function (obj, type) {
    var err;
    Iif (obj.__metadata.type !== type) {
      if (sputils.DEBUG) {
        err = new TypeError([
          'Do not know how to handle an object with __metadata ===',
          obj.__metadata.type
        ].join(''));
 
        console.warn(err);
      }
 
      return false;
    }
 
    return true;
  };
 
  /**
   * @summary
   * takes an object of type `Microsoft.Office.Server.Search.REST.SearchResult`,
   * and gets the actual result rows.
   * @param {Microsoft.Office.Server.Search.REST.SearchResult} postqueryObject
   * the postquery object of the result from doing a request to the search API.
   * @returns {Array<SP.SimpleDataRow>} the result rows
   * @example
   * sputils.search.postSearch({Querytext: '*'})
   *   .then(function (result) {
   *     var rows = sputils.search.extractResultRows(result);
   *     return rows;
   *   });
   */
  var extractResultRows = function (postqueryObject) {
    var type = 'Microsoft.Office.Server.Search.REST.SearchResult';
    Iif (!checkType(postqueryObject, type)) {
      return {};
    }
 
    return postqueryObject.PrimaryQueryResult.RelevantResults.Table.Rows.results;
  };
 
  /**
   * @summary
   * Takes an object returned from the SP Search API, which contains
   * a `Cells` property, which in turn, contains the data in the form
   * of key/value pairs.
   * @param {SP.SimpleDataRow} row - the row.
   * @returns {object} - the object hash representation of the row.
   * @example
   * sputils.search.postSearch({Querytext: '*'})
   *   .then(function (result) {
   *     var rows = sputils.search.extractResultRows(result);
   *     return sputils.fjs.map(
   *       sputils.search.mapRowToHash,
   *       rows);
   *   })
   *   .then(function (parsed) {
   *     console.log(parsed);
   *   });
   */
  var mapRowToHash = function (row) {
    var type = 'SP.SimpleDataRow';
    Iif (!checkType(row, type)) {
      return {};
    }
 
    var kvPairs = row.Cells.results;
 
    var map = fjs.fold(function (out, next) {
      out[next.Key] = next.Value;
      return out;
    }, {});
 
    return map(kvPairs);
  };
 
  /** @namespace */
  sputils.search = {
    searchCfgExample: searchCfgExample,
    postSearch: postSearch,
    mapRowToHash: mapRowToHash,
    extractResultRows: extractResultRows
  };
})();