예제 #1
0
    def count(cls, filter=None, **kwargs):
        """Return a count of documents matching the filter"""
        from mongoframes.queries import Condition, Group, to_refs

        if isinstance(filter, (Condition, Group)):
            filter = filter.to_dict()

        filter = to_refs(filter)

        if filter:
            return cls.get_collection().count_documents(
                to_refs(filter), **kwargs)
        else:
            return cls.get_collection().estimated_document_count(**kwargs)
예제 #2
0
    def many(cls, filter=None, **kwargs):
        """Return a list of documents matching the filter"""
        from mongoframes.queries import Condition, Group, to_refs

        # Flatten the projection
        kwargs['projection'], references, subs = \
                cls._flatten_projection(
                    kwargs.get('projection', cls._default_projection)
                    )

        # Find the documents
        if isinstance(filter, (Condition, Group)):
            filter = filter.to_dict()

        documents = list(cls.get_collection().find(to_refs(filter), **kwargs))

        # Dereference the documents (if required)
        if references:
            cls._dereference(documents, references)

        # Add sub-frames to the documents (if required)
        if subs:
            cls._apply_sub_frames(documents, subs)

        return [cls(d) for d in documents]
예제 #3
0
    def insert_many(cls, documents):
        """Insert a list of documents"""
        from mongoframes.queries import to_refs

        # Ensure all documents have been converted to frames
        frames = cls._ensure_frames(documents)

        assert len([f for f in frames if '_id' in f._document]) == 0, \
                "Can't insert documents with `_id`s"

        # Send insert signal
        signal('insert').send(cls, frames=frames)

        # Prepare the documents to be inserted
        documents = [to_refs(f._document) for f in frames]

        # Bulk insert
        ids = cls.get_collection().insert_many(documents).inserted_ids

        # Apply the Ids to the frames
        for i, id in enumerate(ids):
            frames[i]._id = id

        # Send inserted signal
        signal('inserted').send(cls, frames=frames)

        return frames
예제 #4
0
    def update(self, *fields):
        """
        Update this document. Optionally a specific list of fields to update can
        be specified.
        """
        from mongoframes.queries import to_refs

        assert '_id' in self._document, "Can't update documents without `_id`"

        # Send update signal
        signal('update').send(self.__class__, frames=[self])

        # Check for selective updates
        if len(fields) > 0:
            document = {}
            for field in fields:
                document[field] = self._path_to_value(field, self._document)
        else:
            document = self._document

        # Prepare the document to be updated
        document = to_refs(document)
        document.pop('_id', None)

        # Update the document
        self.get_collection().update_one({'_id': self._id}, {'$set': document})

        # Send updated signal
        signal('updated').send(self.__class__, frames=[self])
예제 #5
0
    def one(cls, filter=None, **kwargs):
        """Return the first document matching the filter"""
        from mongoframes.queries import Condition, Group, to_refs

        # Flatten the projection
        kwargs['projection'], references, subs = \
                cls._flatten_projection(
                    kwargs.get('projection', cls._default_projection)
                    )

        # Find the document
        if isinstance(filter, (Condition, Group)):
            filter = filter.to_dict()

        document = cls.get_collection().find_one(to_refs(filter), **kwargs)

        # Make sure we found a document
        if not document:
            return

        # Dereference the document (if required)
        if references:
            cls._dereference([document], references)

        # Add sub-frames to the document (if required)
        if subs:
            cls._apply_sub_frames([document], subs)

        return cls(document)
예제 #6
0
    def many(cls, filter=None, **kwargs):
        """Return a list of documents matching the filter"""
        from mongoframes.queries import Condition, Group, to_refs

        # Flatten the projection
        kwargs['projection'], references, subs = \
                cls._flatten_projection(
                    kwargs.get('projection', cls._default_projection)
                    )

        # Find the documents
        if isinstance(filter, (Condition, Group)):
            filter = filter.to_dict()

        documents = list(cls.get_collection().find(to_refs(filter), **kwargs))

        # Dereference the documents (if required)
        if references:
            cls._dereference(documents, references)

        # Add sub-frames to the documents (if required)
        if subs:
            cls._apply_sub_frames(documents, subs)

        return [cls(d) for d in documents]
예제 #7
0
    def update(self, *fields):
        """
        Update this document. Optionally a specific list of fields to update can
        be specified.
        """
        from mongoframes.queries import to_refs

        assert '_id' in self._document, "Can't update documents without `_id`"

        # Send update signal
        signal('update').send(self.__class__, frames=[self])

        # Check for selective updates
        if len(fields) > 0:
            document = {}
            for field in fields:
                document[field] = self._path_to_value(field, self._document)
        else:
            document = self._document

        # Prepare the document to be updated
        document = to_refs(document)
        document.pop('_id', None)

        # Update the document
        self.get_collection().update_one({'_id': self._id}, {'$set': document})

        # Send updated signal
        signal('updated').send(self.__class__, frames=[self])
예제 #8
0
    def one(cls, filter=None, **kwargs):
        """Return the first document matching the filter"""
        from mongoframes.queries import Condition, Group, to_refs

        # Flatten the projection
        kwargs['projection'], references, subs = \
                cls._flatten_projection(
                    kwargs.get('projection', cls._default_projection)
                    )

        # Find the document
        if isinstance(filter, (Condition, Group)):
            filter = filter.to_dict()

        document = cls.get_collection().find_one(to_refs(filter), **kwargs)

        # Make sure we found a document
        if not document:
            return

        # Dereference the document (if required)
        if references:
            cls._dereference([document], references)

        # Add sub-frames to the document (if required)
        if subs:
            cls._apply_sub_frames([document], subs)

        return cls(document)
예제 #9
0
    def count(cls, filter=None, **kwargs):
        """Return a count of documents matching the filter"""
        from mongoframes.queries import Condition, Group, to_refs

        if isinstance(filter, (Condition, Group)):
            filter = filter.to_dict()

        return cls.get_collection().count(to_refs(filter), **kwargs)
예제 #10
0
 def nullify(cls, ref_cls, field, frames):
     """Nullify a reference field (does not emit signals)"""
     from mongoframes.queries import to_refs
     ids = [to_refs(f[field]) for f in frames if f.get(field)]
     ref_cls.get_collection().update_many(
         {field: {'$in': ids}},
         {'$set': {field: None}}
         )
예제 #11
0
 def nullify(cls, ref_cls, field, frames):
     """Nullify a reference field (does not emit signals)"""
     from mongoframes.queries import to_refs
     ids = [to_refs(f[field]) for f in frames if f.get(field)]
     ref_cls.get_collection().update_many(
         {field: {'$in': ids}},
         {'$set': {field: None}}
         )
예제 #12
0
 def pull(cls, ref_cls, field, frames):
     """Pull references from a list field (does not emit signals)"""
     from mongoframes.queries import to_refs
     ids = [to_refs(f[field]) for f in frames if f.get(field)]
     ref_cls.get_collection().update_many(
         {field: {'$in': ids}},
         {'$pull': {field: {'$in': ids}}}
         )
예제 #13
0
 def pull(cls, ref_cls, field, frames):
     """Pull references from a list field (does not emit signals)"""
     from mongoframes.queries import to_refs
     ids = [to_refs(f[field]) for f in frames if f.get(field)]
     ref_cls.get_collection().update_many(
         {field: {'$in': ids}},
         {'$pull': {field: {'$in': ids}}}
         )
예제 #14
0
    def update_many(cls, documents, *fields):
        """
        Update multiple documents. Optionally a specific list of fields to
        update can be specified.
        """
        from mongoframes.queries import to_refs

        # Ensure all documents have been converted to frames
        frames = cls._ensure_frames(documents)

        all_count = len(documents)
        assert len([f for f in frames if '_id' in f._document]) == all_count, \
                "Can't update documents without `_id`s"

        # Send update signal
        signal('update').send(cls, frames=frames)

        # Prepare the documents to be updated

        # Check for selective updates
        if len(fields) > 0:
            documents = []
            for frame in frames:
                document = {'_id': frame._id}
                for field in fields:
                    document[field] = cls._path_to_value(
                        field,
                        frame._document
                        )
                documents.append(to_refs(document))
        else:
            documents = [to_refs(f._document) for f in frames]

        # Update the documents
        for document in documents:
            _id = document.pop('_id')
            cls.get_collection().update(
                {'_id': _id}, {'$set': document})

        # Send updated signal
        signal('updated').send(cls.__class__, frames=frames)
예제 #15
0
    def update_many(cls, documents, *fields):
        """
        Update multiple documents. Optionally a specific list of fields to
        update can be specified.
        """
        from mongoframes.queries import to_refs

        # Ensure all documents have been converted to frames
        frames = cls._ensure_frames(documents)

        all_count = len(documents)
        assert len([f for f in frames if '_id' in f._document]) == all_count, \
                "Can't update documents without `_id`s"

        # Send update signal
        signal('update').send(cls, frames=frames)

        # Prepare the documents to be updated

        # Check for selective updates
        if len(fields) > 0:
            documents = []
            for frame in frames:
                document = {'_id': frame._id}
                for field in fields:
                    document[field] = cls._path_to_value(
                        field, frame._document)
                documents.append(to_refs(document))
        else:
            documents = [to_refs(f._document) for f in frames]

        # Update the documents
        requests = []
        for document in documents:
            _id = document.pop('_id')
            requests.append(UpdateOne({'_id': _id}, {'$set': document}))

        cls.get_collection().bulk_write(requests)

        # Send updated signal
        signal('updated').send(cls, frames=frames)
예제 #16
0
    def ids(cls, filter=None, **kwargs):
        """Return a list of Ids for documents matching the filter"""
        from mongoframes.queries import Condition, Group, to_refs

        # Find the documents
        if isinstance(filter, (Condition, Group)):
            filter = filter.to_dict()

        documents = cls.get_collection().find(to_refs(filter),
                                              projection={'_id': True},
                                              **kwargs)

        return [d['_id'] for d in list(documents)]
예제 #17
0
    def ids(cls, filter=None, **kwargs):
        """Return a list of Ids for documents matching the filter"""
        from mongoframes.queries import Condition, Group, to_refs

        # Find the documents
        if isinstance(filter, (Condition, Group)):
            filter = filter.to_dict()

        documents = cls.get_collection().find(
            to_refs(filter),
            projection={'_id': True},
            **kwargs
            )

        return [d['_id'] for d in list(documents)]
예제 #18
0
    def insert(self):
        """Insert this document"""
        from mongoframes.queries import to_refs

        # Send insert signal
        signal('insert').send(self.__class__, frames=[self])

        # Prepare the document to be inserted
        document = to_refs(self._document)

        # Insert the document and update the Id
        self._id = self.get_collection().insert_one(document).inserted_id

        # Send inserted signal
        signal('inserted').send(self.__class__, frames=[self])
예제 #19
0
    def insert(self):
        """Insert this document"""
        from mongoframes.queries import to_refs

        # Send insert signal
        signal('insert').send(self.__class__, frames=[self])

        # Prepare the document to be inserted
        document = to_refs(self._document)

        # Insert the document and update the Id
        self._id = self.get_collection().insert_one(document).inserted_id

        # Send inserted signal
        signal('inserted').send(self.__class__, frames=[self])
예제 #20
0
    def inc(cls, account, date, stats):
        """Increment the given stats (`{stat1: amount1, stat2: amount2}`)"""

        incs = {}
        for stat, amount in stats.items():
            for key in cls.get_inc_keys(date, stat):
                incs[f'values.{key}'] = amount

        for scope in ['all', to_refs(account)]:
            cls.get_collection().update((Q.scope == scope).to_dict(), {
                '$set': {
                    'scope': scope
                },
                '$inc': incs
            },
                                        w=0,
                                        upsert=True)
예제 #21
0
    def __init__(self,
                 frame_cls,
                 filter=None,
                 per_page=20,
                 orphans=0,
                 **filter_args):

        # The frame class results are being paginated for
        self._frame_cls = frame_cls

        # The filter applied when selecting results from the database (we
        # flattern the filter at this point which effectively deep copies.
        if isinstance(filter, (Condition, Group)):
            self._filter = filter.to_dict()
        else:
            self._filter = to_refs(filter)

        # Any additional filter arguments applied when selecting results such as
        # sort and projection,
        self._filter_args = filter_args

        # The number of results that will be displayed per page
        self._per_page = per_page

        # If a value is specified for orphans then the last page will be able to
        # hold the additional results (up to the value of orphans). This can
        # help prevent users being presented with pages contain only a few
        # results.
        self._orphans = orphans

        # Count the total results being paginated
        self._items_count = frame_cls.count(self._filter)

        # Calculated the number of pages
        total = self._items_count - orphans
        self._page_count = max(1,
                               int(math.ceil(total / float(self._per_page))))

        # Create a list of page number that can be used to navigate the results
        self._page_numbers = range(1, self._page_count + 1)
예제 #22
0
 def cascade(cls, ref_cls, field, frames):
     """Apply a cascading delete (does not emit signals)"""
     from mongoframes.queries import to_refs
     ids = [to_refs(f[field]) for f in frames if f.get(field)]
     ref_cls.get_collection().delete_many({'_id': {'$in': ids}})
예제 #23
0
 def cascade(cls, ref_cls, field, frames):
     """Apply a cascading delete (does not emit signals)"""
     from mongoframes.queries import to_refs
     ids = [to_refs(f[field]) for f in frames if f.get(field)]
     ref_cls.get_collection().delete_many({'_id': {'$in': ids}})