function SearchParameters(newParameters) {
  var params = newParameters ? SearchParameters._parseNumbers(newParameters) : {};

  /**
   * Targeted index. This parameter is mandatory.
   * @member {string}
   */
  this.index = params.index || '';

  // Query
  /**
   * Query string of the instant search. The empty string is a valid query.
   * @member {string}
   * @see https://www.algolia.com/doc/rest#param-query
   */
  this.query = params.query || '';

  // Facets
  /**
   * This attribute contains the list of all the conjunctive facets
   * used. This list will be added to requested facets in the
   * [facets attribute](https://www.algolia.com/doc/rest-api/search#param-facets) sent to algolia.
   * @member {string[]}
   */
  this.facets = params.facets || [];
  /**
   * This attribute contains the list of all the disjunctive facets
   * used. This list will be added to requested facets in the
   * [facets attribute](https://www.algolia.com/doc/rest-api/search#param-facets) sent to algolia.
   * @member {string[]}
   */
  this.disjunctiveFacets = params.disjunctiveFacets || [];
  /**
   * This attribute contains the list of all the hierarchical facets
   * used. This list will be added to requested facets in the
   * [facets attribute](https://www.algolia.com/doc/rest-api/search#param-facets) sent to algolia.
   * Hierarchical facets are a sub type of disjunctive facets that
   * let you filter faceted attributes hierarchically.
   * @member {string[]|object[]}
   */
  this.hierarchicalFacets = params.hierarchicalFacets || [];

  // Refinements
  /**
   * This attribute contains all the filters that need to be
   * applied on the conjunctive facets. Each facet must be properly
   * defined in the `facets` attribute.
   *
   * The key is the name of the facet, and the `FacetList` contains all
   * filters selected for the associated facet name.
   *
   * When querying algolia, the values stored in this attribute will
   * be translated into the `facetFilters` attribute.
   * @member {Object.<string, SearchParameters.FacetList>}
   */
  this.facetsRefinements = params.facetsRefinements || {};
  /**
   * This attribute contains all the filters that need to be
   * excluded from the conjunctive facets. Each facet must be properly
   * defined in the `facets` attribute.
   *
   * The key is the name of the facet, and the `FacetList` contains all
   * filters excluded for the associated facet name.
   *
   * When querying algolia, the values stored in this attribute will
   * be translated into the `facetFilters` attribute.
   * @member {Object.<string, SearchParameters.FacetList>}
   */
  this.facetsExcludes = params.facetsExcludes || {};
  /**
   * This attribute contains all the filters that need to be
   * applied on the disjunctive facets. Each facet must be properly
   * defined in the `disjunctiveFacets` attribute.
   *
   * The key is the name of the facet, and the `FacetList` contains all
   * filters selected for the associated facet name.
   *
   * When querying algolia, the values stored in this attribute will
   * be translated into the `facetFilters` attribute.
   * @member {Object.<string, SearchParameters.FacetList>}
   */
  this.disjunctiveFacetsRefinements = params.disjunctiveFacetsRefinements || {};
  /**
   * This attribute contains all the filters that need to be
   * applied on the numeric attributes.
   *
   * The key is the name of the attribute, and the value is the
   * filters to apply to this attribute.
   *
   * When querying algolia, the values stored in this attribute will
   * be translated into the `numericFilters` attribute.
   * @member {Object.<string, SearchParameters.OperatorList>}
   */
  this.numericRefinements = params.numericRefinements || {};
  /**
   * This attribute contains all the tags used to refine the query.
   *
   * When querying algolia, the values stored in this attribute will
   * be translated into the `tagFilters` attribute.
   * @member {string[]}
   */
  this.tagRefinements = params.tagRefinements || [];
  /**
   * This attribute contains all the filters that need to be
   * applied on the hierarchical facets. Each facet must be properly
   * defined in the `hierarchicalFacets` attribute.
   *
   * The key is the name of the facet, and the `FacetList` contains all
   * filters selected for the associated facet name. The FacetList values
   * are structured as a string that contain the values for each level
   * separated by the configured separator.
   *
   * When querying algolia, the values stored in this attribute will
   * be translated into the `facetFilters` attribute.
   * @member {Object.<string, SearchParameters.FacetList>}
   */
  this.hierarchicalFacetsRefinements = params.hierarchicalFacetsRefinements || {};

  /**
   * Contains the numeric filters in the raw format of the Algolia API. Setting
   * this parameter is not compatible with the usage of numeric filters methods.
   * @see https://www.algolia.com/doc/javascript#numericFilters
   * @member {string}
   */
  this.numericFilters = params.numericFilters;

  /**
   * Contains the tag filters in the raw format of the Algolia API. Setting this
   * parameter is not compatible with the of the add/remove/toggle methods of the
   * tag api.
   * @see https://www.algolia.com/doc/rest#param-tagFilters
   * @member {string}
   */
  this.tagFilters = params.tagFilters;

  /**
   * Contains the optional tag filters in the raw format of the Algolia API.
   * @see https://www.algolia.com/doc/rest#param-tagFilters
   * @member {string}
   */
  this.optionalTagFilters = params.optionalTagFilters;

  /**
   * Contains the optional facet filters in the raw format of the Algolia API.
   * @see https://www.algolia.com/doc/rest#param-tagFilters
   * @member {string}
   */
  this.optionalFacetFilters = params.optionalFacetFilters;


  // Misc. parameters
  /**
   * Number of hits to be returned by the search API
   * @member {number}
   * @see https://www.algolia.com/doc/rest#param-hitsPerPage
   */
  this.hitsPerPage = params.hitsPerPage;
  /**
   * Number of values for each faceted attribute
   * @member {number}
   * @see https://www.algolia.com/doc/rest#param-maxValuesPerFacet
   */
  this.maxValuesPerFacet = params.maxValuesPerFacet;
  /**
   * The current page number
   * @member {number}
   * @see https://www.algolia.com/doc/rest#param-page
   */
  this.page = params.page || 0;
  /**
   * How the query should be treated by the search engine.
   * Possible values: prefixAll, prefixLast, prefixNone
   * @see https://www.algolia.com/doc/rest#param-queryType
   * @member {string}
   */
  this.queryType = params.queryType;
  /**
   * How the typo tolerance behave in the search engine.
   * Possible values: true, false, min, strict
   * @see https://www.algolia.com/doc/rest#param-typoTolerance
   * @member {string}
   */
  this.typoTolerance = params.typoTolerance;

  /**
   * Number of characters to wait before doing one character replacement.
   * @see https://www.algolia.com/doc/rest#param-minWordSizefor1Typo
   * @member {number}
   */
  this.minWordSizefor1Typo = params.minWordSizefor1Typo;
  /**
   * Number of characters to wait before doing a second character replacement.
   * @see https://www.algolia.com/doc/rest#param-minWordSizefor2Typos
   * @member {number}
   */
  this.minWordSizefor2Typos = params.minWordSizefor2Typos;
  /**
   * Configure the precision of the proximity ranking criterion
   * @see https://www.algolia.com/doc/rest#param-minProximity
   */
  this.minProximity = params.minProximity;
  /**
   * Should the engine allow typos on numerics.
   * @see https://www.algolia.com/doc/rest#param-allowTyposOnNumericTokens
   * @member {boolean}
   */
  this.allowTyposOnNumericTokens = params.allowTyposOnNumericTokens;
  /**
   * Should the plurals be ignored
   * @see https://www.algolia.com/doc/rest#param-ignorePlurals
   * @member {boolean}
   */
  this.ignorePlurals = params.ignorePlurals;
  /**
   * Restrict which attribute is searched.
   * @see https://www.algolia.com/doc/rest#param-restrictSearchableAttributes
   * @member {string}
   */
  this.restrictSearchableAttributes = params.restrictSearchableAttributes;
  /**
   * Enable the advanced syntax.
   * @see https://www.algolia.com/doc/rest#param-advancedSyntax
   * @member {boolean}
   */
  this.advancedSyntax = params.advancedSyntax;
  /**
   * Enable the analytics
   * @see https://www.algolia.com/doc/rest#param-analytics
   * @member {boolean}
   */
  this.analytics = params.analytics;
  /**
   * Tag of the query in the analytics.
   * @see https://www.algolia.com/doc/rest#param-analyticsTags
   * @member {string}
   */
  this.analyticsTags = params.analyticsTags;
  /**
   * Enable the synonyms
   * @see https://www.algolia.com/doc/rest#param-synonyms
   * @member {boolean}
   */
  this.synonyms = params.synonyms;
  /**
   * Should the engine replace the synonyms in the highlighted results.
   * @see https://www.algolia.com/doc/rest#param-replaceSynonymsInHighlight
   * @member {boolean}
   */
  this.replaceSynonymsInHighlight = params.replaceSynonymsInHighlight;
  /**
   * Add some optional words to those defined in the dashboard
   * @see https://www.algolia.com/doc/rest#param-optionalWords
   * @member {string}
   */
  this.optionalWords = params.optionalWords;
  /**
   * Possible values are "lastWords" "firstWords" "allOptional" "none" (default)
   * @see https://www.algolia.com/doc/rest#param-removeWordsIfNoResults
   * @member {string}
   */
  this.removeWordsIfNoResults = params.removeWordsIfNoResults;
  /**
   * List of attributes to retrieve
   * @see https://www.algolia.com/doc/rest#param-attributesToRetrieve
   * @member {string}
   */
  this.attributesToRetrieve = params.attributesToRetrieve;
  /**
   * List of attributes to highlight
   * @see https://www.algolia.com/doc/rest#param-attributesToHighlight
   * @member {string}
   */
  this.attributesToHighlight = params.attributesToHighlight;
  /**
   * Code to be embedded on the left part of the highlighted results
   * @see https://www.algolia.com/doc/rest#param-highlightPreTag
   * @member {string}
   */
  this.highlightPreTag = params.highlightPreTag;
  /**
   * Code to be embedded on the right part of the highlighted results
   * @see https://www.algolia.com/doc/rest#param-highlightPostTag
   * @member {string}
   */
  this.highlightPostTag = params.highlightPostTag;
  /**
   * List of attributes to snippet
   * @see https://www.algolia.com/doc/rest#param-attributesToSnippet
   * @member {string}
   */
  this.attributesToSnippet = params.attributesToSnippet;
  /**
   * Enable the ranking informations in the response, set to 1 to activate
   * @see https://www.algolia.com/doc/rest#param-getRankingInfo
   * @member {number}
   */
  this.getRankingInfo = params.getRankingInfo;
  /**
   * Remove duplicates based on the index setting attributeForDistinct
   * @see https://www.algolia.com/doc/rest#param-distinct
   * @member {boolean|number}
   */
  this.distinct = params.distinct;
  /**
   * Center of the geo search.
   * @see https://www.algolia.com/doc/rest#param-aroundLatLng
   * @member {string}
   */
  this.aroundLatLng = params.aroundLatLng;
  /**
   * Center of the search, retrieve from the user IP.
   * @see https://www.algolia.com/doc/rest#param-aroundLatLngViaIP
   * @member {boolean}
   */
  this.aroundLatLngViaIP = params.aroundLatLngViaIP;
  /**
   * Radius of the geo search.
   * @see https://www.algolia.com/doc/rest#param-aroundRadius
   * @member {number}
   */
  this.aroundRadius = params.aroundRadius;
  /**
   * Precision of the geo search.
   * @see https://www.algolia.com/doc/rest#param-aroundPrecision
   * @member {number}
   */
  this.minimumAroundRadius = params.minimumAroundRadius;
  /**
   * Precision of the geo search.
   * @see https://www.algolia.com/doc/rest#param-minimumAroundRadius
   * @member {number}
   */
  this.aroundPrecision = params.aroundPrecision;
  /**
   * Geo search inside a box.
   * @see https://www.algolia.com/doc/rest#param-insideBoundingBox
   * @member {string}
   */
  this.insideBoundingBox = params.insideBoundingBox;
  /**
   * Geo search inside a polygon.
   * @see https://www.algolia.com/doc/rest#param-insidePolygon
   * @member {string}
   */
  this.insidePolygon = params.insidePolygon;
  /**
   * Allows to specify an ellipsis character for the snippet when we truncate the text
   * (added before and after if truncated).
   * The default value is an empty string and we recommend to set it to "…"
   * @see https://www.algolia.com/doc/rest#param-insidePolygon
   * @member {string}
   */
  this.snippetEllipsisText = params.snippetEllipsisText;
  /**
   * Allows to specify some attributes name on which exact won't be applied.
   * Attributes are separated with a comma (for example "name,address" ), you can also use a
   * JSON string array encoding (for example encodeURIComponent('["name","address"]') ).
   * By default the list is empty.
   * @see https://www.algolia.com/doc/rest#param-disableExactOnAttributes
   * @member {string|string[]}
   */
  this.disableExactOnAttributes = params.disableExactOnAttributes;
  /**
   * Applies 'exact' on single word queries if the word contains at least 3 characters
   * and is not a stop word.
   * Can take two values: true or false.
   * By default, its set to false.
   * @see https://www.algolia.com/doc/rest#param-enableExactOnSingleWordQuery
   * @member {boolean}
   */
  this.enableExactOnSingleWordQuery = params.enableExactOnSingleWordQuery;

  // Undocumented parameters, still needed otherwise we fail
  this.offset = params.offset;
  this.length = params.length;

  var self = this;
  forOwn(params, function checkForUnknownParameter(paramValue, paramName) {
    if (SearchParameters.PARAMETERS.indexOf(paramName) === -1) {
      self[paramName] = paramValue;
    }
  });
}