Example #1
0
    def __query_spec(self):
        """Get the spec to use for a query.
        """
        operators = {}
        if self.__ordering:
            operators["$orderby"] = self.__ordering
        if self.__explain:
            operators["$explain"] = True
        if self.__hint:
            operators["$hint"] = self.__hint
        if self.__snapshot:
            operators["$snapshot"] = True
        if self.__max_scan:
            operators["$maxScan"] = self.__max_scan
        if self.__collection.database.connection.is_mongos:
            read_pref = {
                'mode': read_preferences.mongos_mode(self.__read_preference)
            }

            if self.__tag_sets and self.__tag_sets != [{}]:
                read_pref['tags'] = self.__tag_sets

            operators['$readPreference'] = read_pref

        if operators:
            # Make a shallow copy so we can cleanly rewind or clone.
            spec = self.__spec.copy()
            if "$query" not in spec:
                # $query has to come first
                spec = SON({"$query": spec})
            spec.update(operators)
            return spec
        # Have to wrap with $query if "query" is the first key.
        # We can't just use $query anytime "query" is a key as
        # that breaks commands like count and find_and_modify.
        # Checking spec.keys()[0] covers the case that the spec
        # was passed as an instance of SON or OrderedDict.
        elif (
                "query" in self.__spec and
            (len(self.__spec) == 1 or list(self.__spec.keys())[0] == "query")):
            return SON({"$query": self.__spec})

        return self.__spec
Example #2
0
    def __query_spec(self):
        """Get the spec to use for a query.
        """
        operators = {}
        if self.__ordering:
            operators["$orderby"] = self.__ordering
        if self.__explain:
            operators["$explain"] = True
        if self.__hint:
            operators["$hint"] = self.__hint
        if self.__snapshot:
            operators["$snapshot"] = True
        if self.__max_scan:
            operators["$maxScan"] = self.__max_scan
        if self.__collection.database.connection.is_mongos:
            read_pref = {
                'mode': read_preferences.mongos_mode(self.__read_preference)}

            if self.__tag_sets and self.__tag_sets != [{}]:
                read_pref['tags'] = self.__tag_sets

            operators['$readPreference'] = read_pref

        if operators:
            # Make a shallow copy so we can cleanly rewind or clone.
            spec = self.__spec.copy()
            if "$query" not in spec:
                # $query has to come first
                spec = SON({"$query": spec})
            spec.update(operators)
            return spec
        # Have to wrap with $query if "query" is the first key.
        # We can't just use $query anytime "query" is a key as
        # that breaks commands like count and find_and_modify.
        # Checking spec.keys()[0] covers the case that the spec
        # was passed as an instance of SON or OrderedDict.
        elif ("query" in self.__spec and
              (len(self.__spec) == 1 or self.__spec.keys()[0] == "query")):
                return SON({"$query": self.__spec})

        return self.__spec
Example #3
0
    def __query_spec(self):
        """Get the spec to use for a query.
        """
        operators = {}
        if self.__ordering:
            operators["$orderby"] = self.__ordering
        if self.__explain:
            operators["$explain"] = True
        if self.__hint:
            operators["$hint"] = self.__hint
        if self.__snapshot:
            operators["$snapshot"] = True
        if self.__max_scan:
            operators["$maxScan"] = self.__max_scan
        # Only set $readPreference if it's something other than
        # PRIMARY to avoid problems with mongos versions that
        # don't support read preferences.
        if (self.__collection.database.connection.is_mongos and
            self.__read_preference != ReadPreference.PRIMARY):

            has_tags = self.__tag_sets and self.__tag_sets != [{}]

            # For maximum backwards compatibility, don't set $readPreference
            # for SECONDARY_PREFERRED unless tags are in use. Just rely on
            # the slaveOkay bit (set automatically if read preference is not
            # PRIMARY), which has the same behavior.
            if (self.__read_preference != ReadPreference.SECONDARY_PREFERRED or
                has_tags):

                read_pref = {
                    'mode': read_preferences.mongos_mode(self.__read_preference)
                }
                if has_tags:
                    read_pref['tags'] = self.__tag_sets

                operators['$readPreference'] = read_pref

        if operators:
            # Make a shallow copy so we can cleanly rewind or clone.
            spec = self.__spec.copy()

            # Only commands that can be run on secondaries should have any
            # operators added to the spec.  Command queries can be issued
            # by db.command or calling find_one on $cmd directly
            if self.collection.name == "$cmd":
                # Don't change commands that can't be sent to secondaries
                command_name = spec and spec.keys()[0].lower() or ""
                if command_name not in secondary_ok_commands:
                    return spec
                elif command_name == 'mapreduce':
                    # mapreduce shouldn't be changed if its not inline
                    out = spec.get('out')
                    if not isinstance(out, dict) or not out.get('inline'):
                        return spec

            # White-listed commands must be wrapped in $query.
            if "$query" not in spec:
                # $query has to come first
                spec = SON([("$query", spec)])

            if not isinstance(spec, SON):
                # Ensure the spec is SON. As order is important this will
                # ensure its set before merging in any extra operators.
                spec = SON(spec)

            spec.update(operators)
            return spec
        # Have to wrap with $query if "query" is the first key.
        # We can't just use $query anytime "query" is a key as
        # that breaks commands like count and find_and_modify.
        # Checking spec.keys()[0] covers the case that the spec
        # was passed as an instance of SON or OrderedDict.
        elif ("query" in self.__spec and
              (len(self.__spec) == 1 or self.__spec.keys()[0] == "query")):
            return SON({"$query": self.__spec})

        return self.__spec
Example #4
0
    def __query_spec(self):
        """Get the spec to use for a query.
        """
        operators = {}
        if self.__ordering:
            operators["$orderby"] = self.__ordering
        if self.__explain:
            operators["$explain"] = True
        if self.__hint:
            operators["$hint"] = self.__hint
        if self.__snapshot:
            operators["$snapshot"] = True
        if self.__max_scan:
            operators["$maxScan"] = self.__max_scan
        # Only set $readPreference if it's something other than
        # PRIMARY to avoid problems with mongos versions that
        # don't support read preferences.
        if (self.__collection.database.connection.is_mongos and
            self.__read_preference != ReadPreference.PRIMARY):

            has_tags = self.__tag_sets and self.__tag_sets != [{}]

            # For maximum backwards compatibility, don't set $readPreference
            # for SECONDARY_PREFERRED unless tags are in use. Just rely on
            # the slaveOkay bit (set automatically if read preference is not
            # PRIMARY), which has the same behavior.
            if (self.__read_preference != ReadPreference.SECONDARY_PREFERRED or
                has_tags):

                read_pref = {
                    'mode': read_preferences.mongos_mode(self.__read_preference)
                }
                if has_tags:
                    read_pref['tags'] = self.__tag_sets

                operators['$readPreference'] = read_pref

        if operators:
            # Make a shallow copy so we can cleanly rewind or clone.
            spec = self.__spec.copy()

            # Only commands that can be run on secondaries should have any
            # operators added to the spec.  Command queries can be issued
            # by db.command or calling find_one on $cmd directly
            if self.collection.name == "$cmd":
                # Don't change commands that can't be sent to secondaries
                command_name = spec and list(spec.keys())[0].lower() or ""
                if command_name not in secondary_ok_commands:
                    return spec
                elif command_name == 'mapreduce':
                    # mapreduce shouldn't be changed if its not inline
                    out = spec.get('out')
                    if not isinstance(out, dict) or not out.get('inline'):
                        return spec

            # White-listed commands must be wrapped in $query.
            if "$query" not in spec:
                # $query has to come first
                spec = SON([("$query", spec)])

            if not isinstance(spec, SON):
                # Ensure the spec is SON. As order is important this will
                # ensure its set before merging in any extra operators.
                spec = SON(spec)

            spec.update(operators)
            return spec
        # Have to wrap with $query if "query" is the first key.
        # We can't just use $query anytime "query" is a key as
        # that breaks commands like count and find_and_modify.
        # Checking spec.keys()[0] covers the case that the spec
        # was passed as an instance of SON or OrderedDict.
        elif ("query" in self.__spec and
              (len(self.__spec) == 1 or list(self.__spec.keys())[0] == "query")):
            return SON({"$query": self.__spec})

        return self.__spec
Example #5
0
    def __query_spec(self):
        """Get the spec to use for a query.
        """
        operators = {}
        if self.__ordering:
            operators["$orderby"] = self.__ordering
        if self.__explain:
            operators["$explain"] = True
        if self.__hint:
            operators["$hint"] = self.__hint
        if self.__snapshot:
            operators["$snapshot"] = True
        if self.__max_scan:
            operators["$maxScan"] = self.__max_scan
        if self.__collection.database.connection.is_mongos:
            read_pref = {
                'mode': read_preferences.mongos_mode(self.__read_preference)}

            if self.__tag_sets and self.__tag_sets != [{}]:
                read_pref['tags'] = self.__tag_sets

            operators['$readPreference'] = read_pref

        if operators:
            # Make a shallow copy so we can cleanly rewind or clone.
            spec = self.__spec.copy()

            # Only commands that can be run on secondaries should have any
            # operators added to the spec.  Command queries can be issued
            # by db.command or calling find_one on $cmd directly
            if self.collection.name == "$cmd":
                if not spec:
                    return spec
                # Don't change commands that can't be sent to secondaries
                command_name = spec.keys()[0].lower()
                if command_name not in secondary_ok_commands:
                    return spec
                elif command_name == 'mapreduce':
                    # mapreduce shouldn't be changed if its not inline
                    out = spec.get('out')
                    if not isinstance(out, dict) or not out.get('inline'):
                        return spec
            elif "$query" not in spec:
                # $query has to come first
                spec = SON({"$query": spec})

            if not isinstance(spec, SON):
                # Ensure the spec is SON. As order is important this will
                # ensure its set before merging in any extra operators.
                spec = SON(spec)

            spec.update(operators)
            return spec
        # Have to wrap with $query if "query" is the first key.
        # We can't just use $query anytime "query" is a key as
        # that breaks commands like count and find_and_modify.
        # Checking spec.keys()[0] covers the case that the spec
        # was passed as an instance of SON or OrderedDict.
        elif ("query" in self.__spec and
              (len(self.__spec) == 1 or self.__spec.keys()[0] == "query")):
            return SON({"$query": self.__spec})

        return self.__spec
Example #6
0
    def __query_spec(self):
        """Get the spec to use for a query.
        """
        operators = {}
        if self.__ordering:
            operators["$orderby"] = self.__ordering
        if self.__explain:
            operators["$explain"] = True
        if self.__hint:
            operators["$hint"] = self.__hint
        if self.__snapshot:
            operators["$snapshot"] = True
        if self.__max_scan:
            operators["$maxScan"] = self.__max_scan
        if self.__collection.database.connection.is_mongos:
            read_pref = {
                'mode': read_preferences.mongos_mode(self.__read_preference)
            }

            if self.__tag_sets and self.__tag_sets != [{}]:
                read_pref['tags'] = self.__tag_sets

            operators['$readPreference'] = read_pref

        if operators:
            # Make a shallow copy so we can cleanly rewind or clone.
            spec = self.__spec.copy()

            # Only commands that can be run on secondaries should have any
            # operators added to the spec.  Command queries can be issued
            # by db.command or calling find_one on $cmd directly
            is_cmd = self.collection.name == "$cmd"
            if is_cmd:
                # Don't change commands that can't be sent to secondaries
                command_name = spec.keys()[0].lower()
                if command_name not in secondary_ok_commands:
                    return spec
                elif command_name == 'mapreduce':
                    # mapreduce shouldn't be changed if its not inline
                    out = spec.get('out')
                    if not isinstance(out, dict) or not out.get('inline'):
                        return spec
            elif "$query" not in spec:
                # $query has to come first
                spec = SON({"$query": spec})

            if not isinstance(spec, SON):
                # Ensure the spec is SON. As order is important this will
                # ensure its set before merging in any extra operators.
                spec = SON(spec)

            spec.update(operators)
            return spec
        # Have to wrap with $query if "query" is the first key.
        # We can't just use $query anytime "query" is a key as
        # that breaks commands like count and find_and_modify.
        # Checking spec.keys()[0] covers the case that the spec
        # was passed as an instance of SON or OrderedDict.
        elif ("query" in self.__spec
              and (len(self.__spec) == 1 or self.__spec.keys()[0] == "query")):
            return SON({"$query": self.__spec})

        return self.__spec