22from typing import Mapping , List
33
44from .document import Document
5- from .fileio import FileIO , BinaryFileIO
5+ from .fileio import FileIO
6+
7+
8+ # ^__^
9+ # (oo)\_______
10+ # (_)\ )\/\
11+ # ||----w |
12+ # || ||
13+ # ~~~~~~~~~~~~~~~~~~~~
614
715
816class Collection :
@@ -12,10 +20,11 @@ def __init__(self, col_name: str, binary_file: FileIO) -> None:
1220
1321 # Get the data of existing Database or empty database.
1422 self ._database = self ._binary_file .read ()
15- # print(self._database)
16- # Initiate a default Collection
1723
18- # Check the Collection is already exists or no
24+ self ._cursor : int = 0
25+
26+ # Initiate a default Collection.
27+ # Check the Collection is already exists or no.
1928 if self ._col_name in self ._database .keys ():
2029
2130 # Get the existing Collection
@@ -81,13 +90,202 @@ def insert_all(self, document_list: List[Mapping]) -> int:
8190
8291 # Iterate over all Documents of document_list & Insert one by one.
8392 for document in document_list :
84-
8593 # insert every single document in Database & increment ``doc_count``.
8694 doc_count += self .insert (document )
8795
8896 return doc_count
8997
9098
99+ """ FIND_ONE
100+ def __find_one(self, query: Mapping = None) -> Document | None:
101+ "
102+ Finds a single ``Document`` of ``Collection``.
103+
104+ If ``query`` is None then returns all the ``Documents`` of ``Collection``.
105+
106+ If ``query`` is not None then returns only the first occurrence.
107+
108+ :param query: Condition to search Document
109+ :return: Document
110+ "
111+ # Default result
112+ _result = {}
113+
114+ # Make sure the query implements the ``Mapping`` interface.
115+ if not isinstance(query, Mapping | None):
116+ raise ValueError('Document is not a Dictionary')
117+
118+
119+
120+ # Check if has ``query`` or not
121+ if query is None:
122+ _result = self._collection[self._cursor]
123+ self._reset_cursor()
124+ else:
125+ print(self._cursor)
126+ _result = self._find_document_by_query(query)
127+ self._reset_cursor()
128+ _result = _result[self._cursor]
129+
130+ return _result
131+ """
132+
133+ def find (self , query : Mapping = None , limit : tuple = None ) -> List [Document | None ]:
134+ """
135+ Finds all ``Document`` of ``Collection``.
136+
137+ If ``query`` is None then returns all the ``Documents`` of ``Collection``.
138+
139+ If ``query`` is not None then find returns all the occurrences.
140+
141+ :param limit: Amount of Document to fetch
142+ :param query: Condition to search Document
143+ :return: List of Document
144+ """
145+ # Default result
146+ _result = []
147+
148+ # Make sure the query implements the ``Mapping`` interface.
149+ if not isinstance (query , Mapping | None ):
150+ raise ValueError ('Document is not a Dictionary' )
151+
152+ # if limit, Check everything ok
153+ _limit_start = _limit_end = None
154+
155+ if limit :
156+ if len (limit ) == 2 :
157+ _limit_start = limit [0 ]
158+ _limit_end = limit [1 ]
159+ else :
160+ raise ValueError (f"limit is a tuple of 2 values, { len (limit )} is given." )
161+
162+ # Check if ``query`` is None or not None.
163+ if query is None :
164+ # Check if it has a limit or not. If it has a limit do limit specific tasks.
165+ # Else return the whole Collection.
166+ if limit is not None :
167+ _result = self ._collection [_limit_start : _limit_end ]
168+ else :
169+ _result = self ._collection
170+
171+ return _result
172+
173+ elif query is not None :
174+ if limit :
175+ for i in self ._collection :
176+ _doc = self ._find_document_by_query (query )
177+
178+ # Append Document to the result if found
179+ if _doc :
180+ _result += _doc
181+
182+ # Check the result reached to the limit or not
183+ if len (_result ) >= _limit_end :
184+ break
185+
186+ # Reset the cursor
187+ self ._reset_cursor ()
188+
189+ # Travers limited result
190+ _result = _result [_limit_start : _limit_end ]
191+
192+ else :
193+ for i in self ._collection :
194+ _doc = self ._find_document_by_query (query )
195+
196+ if _doc :
197+ _result += _doc
198+ self ._reset_cursor ()
199+
200+ return _result
201+
202+
203+
204+ def _reset_cursor (self ) -> None :
205+ """
206+ Reset Cursor Pointer to 0th index
207+ :return: None
208+ """
209+ self ._cursor = 0
210+
211+ def _find_document_by_query (self , query : Mapping ) -> List | None :
212+ """
213+ Finds a single ``Document`` of ``Collection``.
214+
215+ Returns None if ``query`` is None of any Document not found.
216+
217+ :param query: Condition to search Document
218+ :return: Document
219+ """
220+ result = []
221+
222+ # Make sure the query implements the ``Mapping`` interface.
223+ if not isinstance (query , Mapping | None ):
224+ raise ValueError ('Document is not a Dictionary' )
225+
226+ # Get the length on Collection
227+ _collection_length = len (self ._collection )
228+
229+ # Iterate all the Documents of Collection
230+ for doc_index in range (self ._cursor , _collection_length ):
231+
232+ # Update ``self._doc_index`` with ``doc_index``, to iterate next Document.
233+ self ._cursor = doc_index + 1
234+
235+ # Get the length on ``query`` to iterate all attributes
236+ _query_length = len (query )
237+
238+ # Typecast ``query`` in to a ``list`` to iterate it.
239+ _query_list = list (query .items ())
240+
241+ # ``_bag_of_query`` indicates the Document is desired or not.
242+ _bag_of_query = [0 ] * _query_length
243+
244+ for i in range (_query_length ):
245+
246+ # Check the ``key`` is belongs to the Documents or not.
247+ if _query_list [i ][0 ] in self ._collection [doc_index ]:
248+
249+ # Check the ``value`` of ``query`` is same to the Document's or not.
250+ if self ._collection [doc_index ][_query_list [i ][0 ]] == _query_list [i ][1 ]:
251+
252+ # If both values are same, then update ``_bag_of_query[i]`` as 1.
253+ _bag_of_query [i ] = 1
254+
255+
256+ else :
257+ continue
258+ else :
259+ continue
260+ # Check if ``_bag_of_query`` contains any `0` or not.
261+ # If it has any value then this is the desired Document.
262+ # Else such Document in Collection.
263+
264+
265+
266+ if 0 not in _bag_of_query :
267+
268+ # return the Document
269+ result .append (self ._collection [doc_index ])
270+
271+ elif doc_index <= _collection_length :
272+ # self._doc_index = doc_index
273+ continue
274+
275+ else :
276+ return None
277+
278+
279+ return result
280+
281+
282+
283+
284+ def count (self , query : Mapping = None , limit : tuple = None ) -> int :
285+ return len (self .find (query = query , limit = limit ))
286+
287+
288+
91289 # ======================== #
92290 def _doc_is_exists (self , doc_id : str | int ) -> bool :
93291 # Iterate over all Documents of Collection
@@ -97,7 +295,7 @@ def _doc_is_exists(self, doc_id: str | int) -> bool:
97295
98296 return False
99297
100- def _get_document_by_id (self , doc_id ) -> Document | str :
298+ def _find_document_by_id (self , doc_id ) -> Document | str :
101299 for doc in self ._collection :
102300 if doc ["_id_" ] == doc_id :
103301 return doc
0 commit comments