diff --git a/README.md b/README.md
index 341eb8a..7be3e34 100644
--- a/README.md
+++ b/README.md
@@ -142,25 +142,26 @@ To delete a record from the database, use the `delete()` method:
 ```python
 Post.delete(1)  # Delete the post with ID 1
 ```
-### Converting to Dictionary and Counting Records
-After performing operations on the model, you can convert records to dictionaries using the `to_dict()` method and count the number of records using the `count()` method.
+## Converting to Dictionary, Counting Records, and Other Query Methods
 
-#### `to_dict` Method
-The `to_dict()` method converts a model instance into a dictionary, making it easier to manipulate and serialize the data.
+This section covers how to convert records to dictionaries, count records, and use various query methods like `first()`, `last()`, `exists()`, `order_by()`, `paginate()`, and `contains()`. These methods are essential for data manipulation, debugging, and optimizing query performance.
 
-**Example:**
+### `to_dict()` Method
+The `to_dict()` method converts a model instance (or a collection of instances) into a dictionary, which is particularly useful for data manipulation and serialization. It makes it easier to work with the data in Python or send it over an API.
+
+#### Example:
 ```python
-# Retrieve a post by ID
-post = Post.get(id=1)
+# Retrieve all posts
+posts = Post.all()
 
-# Convert the post to a dictionary
-post_dict = post.all().to_dict()
-print(post_dict)
-# Output: [{'id': 1, 'title': 'Godfather', 'create_time': '2024-01-01 12:00:00', ...}]
+# Convert the collection of posts to a list of dictionaries
+posts_dict = posts.to_dict()
+print(posts_dict)
+# Output: [{'id': 1, 'title': 'Godfather', 'create_time': '2024-01-01 12:00:00', ...}, {...}]
 ```
 
 #### `count` Method
-The `count()` method allows you to get the number of records in a model's table.
+The `count()` method returns the number of records that match the query. It’s an efficient way to find the size of a dataset without retrieving the actual data.
 
 **Example:**
 ```python
@@ -169,11 +170,21 @@ num_posts = Post.count()
 print(num_posts)  # Output: 10 (if there are 10 posts in the database)
 ```
 
-#### `first()`, `last()`, `exists()`, `order_by()`, and `paginate()`
-- `first():` Returns the first result or None if no results are present.
-- `last():` Returns the last result or None if no results are present.
-- `exists():` Checks if any records exist in the `QuerySet`.
-- `paginate():` Handles pagination of results, allowing you to retrieve subsets of data based on page and page size.
+The `count()` method can also be used after applying filters to count specific records:
+```python
+# Count the number of posts with a specific title
+num_posts_with_title = Post.filter(title='Godfather').count()
+print(num_posts_with_title)  # Output: 3 (if there are 3 posts with the title 'Godfather')
+```
+
+
+
+#### `first()`, `last()`, `exists()`, `order_by()`, `paginate()` and `contains()`
+- **`first()`**: Returns the first result or `None` if no results are present.
+- **`last()`**: Returns the last result or `None` if no results are present.
+- **`exists()`**: Checks if any records exist in the `QuerySet`.
+- **`paginate()`**: Handles pagination of results, allowing you to retrieve subsets of data based on page and page size.
+- **`contains()`**: Performs a case-insensitive search to check if a field contains a specific substring.
 
 **Example:**
 ```python
@@ -190,20 +201,11 @@ last_post = Post.all().last()
 paginated_posts = Post.all().paginate(1, 5)  # Page 1, 5 results per page
 
 # Using multiple querysets in one query
-posts = Post.filter(title='Godfather').order_by('create_time').paginate(1, 4).to_dict()
+posts = Post.all().contains(title='god').order_by('create_time').paginate(1, 4).to_dict()
 ```
 
 These methods are particularly useful for data manipulation and debugging, as they provide a simple way to view and interact with your database records.
 
-## Version 4.2.3
-
-- `first():` Added to return the first result in a `QuerySet`.
-- `last():` Added to return the last result in a `QuerySet`.
-- `exists():` Added to check if any records exist.
-- `paginate():` Added to handle pagination for large result sets.
-
-
-**Important for Developers:** When adding new fields to models, they will default to `NULL`. It’s recommended to recreate the database schema after development is complete to ensure fields have appropriate constraints and default values.
 
 ## Contributing
 
diff --git a/abarorm/fields/__init__.py b/abarorm/fields/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/abarorm/psql.py b/abarorm/psql.py
index f0cd932..87979d0 100644
--- a/abarorm/psql.py
+++ b/abarorm/psql.py
@@ -73,6 +73,42 @@ def paginate(self, page: int, page_size: int):
             # Return a new QuerySet with paginated results
             return self.__class__(paginated_results, self.total_count, page, page_size)
         
+        def contains(self, field: str, value) -> 'QuerySet':
+            """
+            Performs a case-insensitive 'contains' search for the given field and value.
+            Can handle various data types such as strings, numbers, and datetime.
+            
+            :param field: The field name (e.g. 'title').
+            :param value: The value to search for (e.g. substring for strings or a number).
+            :return: A new QuerySet with the filtered results.
+            """
+            filtered_results = []
+            
+            for obj in self.results:
+                field_value = getattr(obj, field, None)
+                
+                # If the field's value is a string
+                if isinstance(field_value, str):
+                    # Perform a case-insensitive substring search
+                    if value.lower() in field_value.lower():
+                        filtered_results.append(obj)
+                # If the field's value is a number (int, float)
+                elif isinstance(field_value, (int, float)):
+                    # Check if the number contains the value as a substring (as string)
+                    if str(value) in str(field_value):
+                        filtered_results.append(obj)
+                # If the field's value is a datetime or date
+                elif isinstance(field_value, (datetime, date)):
+                    # Check if the value is a substring of the date (formatted as string)
+                    if str(value) in field_value.strftime('%Y-%m-%d'):
+                        filtered_results.append(obj)
+                # For other field types, apply an appropriate check (e.g., exact match)
+                elif field_value == value:
+                    filtered_results.append(obj)
+
+            return self.__class__(filtered_results, len(filtered_results), self.page, self.page_size)
+
+        
     
     def __repr__(self):
         field_values = {attr: getattr(self, attr) for attr in self.__class__.__dict__ if isinstance(self.__class__.__dict__[attr], Field)}
diff --git a/abarorm/sqlite.py b/abarorm/sqlite.py
index 949f8ae..ef71412 100644
--- a/abarorm/sqlite.py
+++ b/abarorm/sqlite.py
@@ -72,6 +72,41 @@ def paginate(self, page: int, page_size: int):
             paginated_results = self.results[offset:offset + page_size]
             # Return a new QuerySet with paginated results
             return self.__class__(paginated_results, self.total_count, page, page_size)
+        
+        def contains(self, field: str, value) -> 'QuerySet':
+            """
+            Performs a case-insensitive 'contains' search for the given field and value.
+            Can handle various data types such as strings, numbers, and datetime.
+            
+            :param field: The field name (e.g. 'title').
+            :param value: The value to search for (e.g. substring for strings or a number).
+            :return: A new QuerySet with the filtered results.
+            """
+            filtered_results = []
+            
+            for obj in self.results:
+                field_value = getattr(obj, field, None)
+                
+                # If the field's value is a string
+                if isinstance(field_value, str):
+                    # Perform a case-insensitive substring search
+                    if value.lower() in field_value.lower():
+                        filtered_results.append(obj)
+                # If the field's value is a number (int, float)
+                elif isinstance(field_value, (int, float)):
+                    # Check if the number contains the value as a substring (as string)
+                    if str(value) in str(field_value):
+                        filtered_results.append(obj)
+                # If the field's value is a datetime or date
+                elif isinstance(field_value, (datetime, date)):
+                    # Check if the value is a substring of the date (formatted as string)
+                    if str(value) in field_value.strftime('%Y-%m-%d'):
+                        filtered_results.append(obj)
+                # For other field types, apply an appropriate check (e.g., exact match)
+                elif field_value == value:
+                    filtered_results.append(obj)
+
+            return self.__class__(filtered_results, len(filtered_results), self.page, self.page_size)
 
 
 
diff --git a/setup.py b/setup.py
index fab80e0..c094b43 100644
--- a/setup.py
+++ b/setup.py
@@ -2,7 +2,7 @@
 
 setup(
     name='abarorm',
-    version='5.0.0',
+    version='5.0.2',
     description='abarorm is a lightweight and easy-to-use Object-Relational Mapping (ORM) library for SQLite and PostgreSQL databases in Python. It aims to provide a simple and intuitive interface for managing database models and interactions.',
     long_description=open('README.md').read(),
     long_description_content_type='text/markdown',