Skip to content

Commit

Permalink
Update queries.md documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
tarsil committed Oct 1, 2023
1 parent 91ca252 commit 420676f
Show file tree
Hide file tree
Showing 4 changed files with 244 additions and 3 deletions.
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,10 @@ and pattern of development.

Mongox implements really well some operations with MongoDB but for use cases where [Signals](https://mongoz.tarsild.io/sinals.md),
for example, are needed, Mongox was not aiming at it and also since the creator of Mongoz is the
same as [Mongoz][mongoz] and [Saffier][saffier], the friendly interface to interact is also a must.
same as [Saffier][saffier] and [Saffier][saffier], the friendly interface to interact is also a must.

In the end, there was a need to add Pydantic 2+ with some more extras that was not coming in the
Mongox.

## Mongoz

Expand Down
7 changes: 5 additions & 2 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,12 @@ So why a MongoZ if there is a MongoX? Well, MongoZ is from the same author of [E
[Saffier][saffier], [Mongoz][mongoz] and many other tools out there and they all follow a specific need
and pattern of development.

Mongox implements really well some operations with MongoDB but for use cases where [Signals][./sinals.md],
Mongox implements really well some operations with MongoDB but for use cases where [Signals](./sinals.md),
for example, are needed, Mongox was not aiming at it and also since the creator of Mongoz is the
same as [Mongoz][mongoz] and [Saffier][saffier], the friendly interface to interact is also a must.
same as [Saffier][saffier] and [Edgy][edgy], the friendly interface to interact is also a must.

In the end, there was a need to add Pydantic 2+ with some more extras that was not coming in the
Mongox.

## Mongoz

Expand Down
214 changes: 214 additions & 0 deletions docs/queries.md
Original file line number Diff line number Diff line change
Expand Up @@ -735,6 +735,220 @@ When you need to update many instances in one go, or `in bulk`.
When applying the functions that returns values directly and not managers or querysets,
**you can still apply the operators such as `filter`, `skip`, `sort`...**

## Querying Embedded documents

Querying [embedded documents](./embedded-documents.md) is also easy and here the `queryset` is very powerful in doing it so.

Let us see an example.

```python hl_lines="17"
{!> ../docs_src/queries/embed.py !}
```

We can now create some instances of the `User`.

=== "Manager"

```python hl_lines="5"
access_type = UserType(access_level="admin")

await User.objects.create(
first_name="Mongoz", last_name="ODM", email="[email protected]",
access_level=access_type
)
```

=== "QuerySet"

```python hl_lines="5"
access_type = UserType(access_level="admin")

await User(
first_name="Mongoz", last_name="ODM", email="[email protected]",
access_level=access_type
).create()
```

This will create the following document in the database:

```json
{
"email": "[email protected]", "first_name": "Mongoz", "last_name": "ODM",
"is_active": true, "access_level": {"level": "admin" }
},
```

You can now query the user by embedded document field.

```python
await User.query(User.user_type.level == "admin").get()
```

This is the equivalent to the following filter:

```json
{"access_level.level": "admin" }
```

You can also use the complete embedded document.

```python
await User.query(User.user_type == level).get()
```

This is the equivalent to the following filter:

```json
{"access_level": {"level": "admin"} }
```

!!! Warning
For the [Embedded Documents](./embedded-documents.md) type of query, using the manager it won't
work. **You should use the `queryset` type of approach for the query**.

## The Q operator

This operator was inspired by `Mongox` and extended for Mongoz needs. The credit for the initial
design of the `Q` operator goes to `Mongox`.

The `Q` class contains some useful and quite handy methods to be used in the queries.

```python
from mongoz import Q, Order
```

The `Q` operator is mainly used in the `queryset` and not so much in the `manager` and the main
reason for this is because the `manager` internally manipulates the `Q` operator for you
automatically. Pretty cool, hein?

In order to create, for example a `sort` query, you would usually do this:

```python
users = await User.query().sort(User.email, Order.DESCENDING).all()
```

Where does the `Q` operator enters here? Well, you can see it as a shortcut for your queries.

### Ascending

```python
users = await User.query().sort(Q.asc(User.email)).all()
```

### Descending

```python
users = await User.query().sort(Q.desc(User.email)).all()
```

### In

The `in` operator.

```python
users = await User.query(Q.in_(User.id, [1, 2, 3, 4])).all()
```

### Not In

The `not_in` operator.

```python
users = await User.query(Q.not_in(User.id, [1, 2, 3, 4])).all()
```

### And

```python
users = await User.query(Q.and_(User.email == "[email protected]", User.id > 1)).all()

users = await User.query(User.email == "[email protected]").query(User.id > 1).all()
```

### Or

```python
users = await User.query(Q.or_(User.email == "[email protected]", User.id > 1)).all()
```

### Nor

```python
users = await User.query(Q.nor_(User.email == "[email protected]", User.id > 1)).all()
```

### Not

```python
users = await User.query(Q.not_(User.email == "[email protected]", User.id > 1)).all()
```

### Contains

```python
users = await User.query(Q.contains(User.email == "foo")).all()
```

### IContains

```python
users = await User.query(Q.contains(User.email == "foo")).all()
```

### Pattern

Applies some `$regex` patterns.

```python
users = await User.query(Q.pattern(User.email == r"\w+ foo \w+")).all()
```

### Equals

The `equals` operator.

```python
users = await User.query(Q.eq(User.email, "[email protected]")).all()
```

### Not Equals

The `not equals` operator.

```python
users = await User.query(Q.neq(User.email, "[email protected]")).all()
```

### Where

Applying the mongo `where` operator.

```python
users = await User.query(Q.where(User.email, "[email protected]")).all()
```

### Greater Than

```python
users = await User.query(Q.gt(User.id, 1)).all()
```

### Greater Than Equal

```python
users = await User.query(Q.gte(User.id, 1)).all()
```

### Less Than

```python
users = await User.query(Q.lt(User.id, 20)).all()
```

### Less Than Equal

```python
users = await User.query(Q.lte(User.id, 20)).all()
```

[document]: ./documents.md
21 changes: 21 additions & 0 deletions docs_src/queries/embed.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import mongoz

database_uri = "mongodb://localhost:27017"
registry = mongoz.Registry(database_uri)


class UserType(mongoz.EmbeddedDocument):
level: str = mongoz.String()


class User(mongoz.Document):
is_active: bool = mongoz.Boolean(default=True)
first_name: str = mongoz.String(max_length=50)
last_name: str = mongoz.String(max_length=50)
email: str = mongoz.Email(max_lengh=100)
password: str = mongoz.String(max_length=1000)
user_type: UserType = mongoz.Embed(UserType)

class Meta:
registry = registry
database = "my_db"

0 comments on commit 420676f

Please sign in to comment.