def get_results(self, params=None, result_id=None):
        """
        Return all the results available from the database that fulfill some
        parameter combinations.

        If params is None (or not specified), return all results.

        If params is specified, it must be a dictionary specifying the result
        values we are interested in, with multiple values specified as lists.

        For example, if the following params value is used::

            params = {
            'param1': 'value1',
            'param2': ['value2', 'value3']
            }

        the database will be queried for results having param1 equal to value1,
        and param2 equal to value2 or value3.

        Not specifying a value for all the available parameters is allowed:
        unspecified parameters are assumed to be 'free', and can take any
        value.

        Returns:
            A list of results matching the query. Returned results have the
            same structure as results inserted with the insert_result method.
        """

        # In this case, return all results
        # A cast to dict is necessary, since self.db.table() contains TinyDB's
        # Document object (which is simply a wrapper for a dictionary, thus the
        # simple cast).
        if result_id is not None:
            return [dict(i) for i in self.db.table('results').all() if
                    i['meta']['id'] == result_id]

        if params is None:
            return [dict(i) for i in self.db.table('results').all()]

        # Verify parameter format is correct
        all_params = set(['RngRun'] + self.get_params())
        param_subset = set(params.keys())
        if (not all_params.issuperset(param_subset)):
            raise ValueError(
                '%s:\nParameters: %s\nQuery: %s' % (
                    'Specified parameter keys do not match database format',
                    all_params,
                    param_subset))

        # Convert values that are not lists into lists to later perform
        # iteration over values more naturally. Perform this on a new
        # dictionary not to modify the original copy.
        query_params = {}
        for key in params:
            if not isinstance(params[key], list):
                query_params[key] = [params[key]]
            else:
                query_params[key] = params[key]

        # Handle case where query params has no keys
        if not query_params.keys():
            return [dict(i) for i in self.db.table('results').all()]

        # Create the TinyDB query
        # In the docstring example above, this is equivalent to:
        # AND(OR(param1 == value1), OR(param2 == value2, param2 == value3))
        query = reduce(and_, [reduce(or_, [
            where('params')[key] == v for v in value]) for key, value in
                              query_params.items()])

        return [dict(i) for i in self.db.table('results').search(query)]
Return all the results available from the database that fulfill some
        parameter combinations.

        If params is None (or not specified), return all results.

        If params is specified, it must be a dictionary specifying the result
        values we are interested in, with multiple values specified as lists.

        For example, if the following params value is used::

            params = {
            'param1': 'value1',
            'param2': ['value2', 'value3']
            }

        the database will be queried for results having param1 equal to value1,
        and param2 equal to value2 or value3.

        Not specifying a value for all the available parameters is allowed:
        unspecified parameters are assumed to be 'free', and can take any
        value.

        Returns:
            A list of results matching the query. Returned results have the
            same structure as results inserted with the insert_result method.