Skip to content

Commit

Permalink
Version 1.3.8
Browse files Browse the repository at this point in the history
Merge pull request #36 from Djcharles26/work
  • Loading branch information
Djcharles26 authored Jul 2, 2024
2 parents 3bb40b6 + 468acc0 commit 889efcc
Show file tree
Hide file tree
Showing 6 changed files with 158 additions and 146 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
dist/
build/
*.egg-info/
__pycache__/
__pycache__/

env/
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
## Methods
- Added no_cursor_timeout option in find methods
- Updated how populate works with dictionaries
290 changes: 150 additions & 140 deletions pymongoose/methods.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,165 +190,175 @@ def _populate(schema, populate, aggregate: list, parent=""):

pipeline.append({"$project": project})

e = {
"$lookup": {
"from": aux_schema["ref"],
"let": {f"var": f"${parent + pop['path']}"},
"pipeline": pipeline,
"as": parent + pop["path"]
}
}

aggregate.append(e)
#Unwind result
unwind = {
"path": f"${parent + pop['path']}",
"preserveNullAndEmptyArrays": True
}
aggregate.append({"$unwind": unwind})

if "match" in pop:
aggregate.append({"$match": {f"{parent}{pop['path']}.{k}": v for k, v in pop["match"].items()}})

wL = False

if "options" in pop: #If has attached populates

##Recursively call to function with respective schema

wL = _populate(schemas[aux_schema["ref"]], pop["options"], aggregate, parent + pop["path"] + ".")

"""
If current isList is true:
If parent exists:
Current parent should be added in _id
## This means two things, The first is that the current path is a dict and contains values to be populated
## Or, the schema is not correct
if ("ref" not in aux_schema):
if ("options" in pop):
_populate (aux_schema, pop["options"], aggregate, pop["path"] + ".")
else:
_id = "$_id"
path: {"$push": "$parent.path"}
doc: {"$first": "$$ROOT"}
add $replaceRoot with
$_id,
parent: {
"$mergeObjects": [
"$doc", {"_id": "$_id._id"}, to obtain real _id
{
"$parent": {
"$mergeObjects": ["$parent", {"path": "$path"}]
}
}
]
}
"""

# Group and replace to have a correct object
if isList:
group = {}
_id = {}

parentAux = parent
parentRoot = parentAux

# If parent has a dot, remove it and get the parentRoot (The first position)
if(parent.find(".") > 0):
parentRoot = parent.split(".")[0]

# If parent is not empty it means is required to add in _id each parent participant
if len(parent) > 0:
parentAux = parent[:-1]

_id = {
"_id": f"$_id",
raise MongoException(
message=f"Schema {pop['path']} is not correct, Missing 'ref'"
)
else:
e = {
"$lookup": {
"from": aux_schema["ref"],
"let": {f"var": f"${parent + pop['path']}"},
"pipeline": pipeline,
"as": parent + pop["path"]
}
}

# Generate a list of parents splitted by .
parents_list = parentAux.split (".")
aggregate.append(e)
#Unwind result
unwind = {
"path": f"${parent + pop['path']}",
"preserveNullAndEmptyArrays": True
}
aggregate.append({"$unwind": unwind})

# Lambda to generate the correct format
# For key its required to be with _ and for _id value is required a .
#e.g
# 'components': "$components._id",
# 'components_children': '$components.children._id'
formatted_parent = lambda c, limit: f"{c}".join (parents_list [0:limit + 1])
if "match" in pop:
aggregate.append({"$match": {f"{parent}{pop['path']}.{k}": v for k, v in pop["match"].items()}})

for i, _ in enumerate(parents_list):
idd = "$" + formatted_parent ('.', i) + "._id"
_id [formatted_parent ('_', i)] = idd
wL = False

else:
if "options" in pop: #If has attached populates

##Recursively call to function with respective schema

_id = f"$_id"
wL = _populate(schemas[aux_schema["ref"]], pop["options"], aggregate, parent + pop["path"] + ".")

# Group the path (The current populated item) in an array, if path has a dot, it means the populated item is inside an object
# Which doesn't care, so its required to take only the first name of the path.
"""
E.g.
for the schema:
users: [
{
user_id: {
type: Types.ObjectId,
required: True,
ref: "users"
},
count: {
type: Types.Number,
required: True
If current isList is true:
If parent exists:
Current parent should be added in _id
else:
_id = "$_id"
path: {"$push": "$parent.path"}
doc: {"$first": "$$ROOT"}
add $replaceRoot with
$_id,
parent: {
"$mergeObjects": [
"$doc", {"_id": "$_id._id"}, to obtain real _id
{
"$parent": {
"$mergeObjects": ["$parent", {"path": "$path"}]
}
}
}
]
The path for populate would be /users.user_id/
]
}
"""

popAux = pop["path"]
if popAux.find(".") > 0:
popAux = popAux.split(".")[0]
# Group and replace to have a correct object
if isList:
group = {}
_id = {}

parentAux = parent
parentRoot = parentAux

group["_id"] = _id
group[popAux] = {"$push": f"${parent}{popAux}"}
group["doc"] = {"$first": "$$ROOT"}
# If parent has a dot, remove it and get the parentRoot (The first position)
if(parent.find(".") > 0):
parentRoot = parent.split(".")[0]

# print (group)
# If parent is not empty it means is required to add in _id each parent participant
if len(parent) > 0:
parentAux = parent[:-1]

# print (f"path: {pop['path']}")
# print (f"N_parents {n_parents}")
# print (f"Parent: {parentAux}")
# print (f"Was List: {wL}")

aggregate.append({
"$group": group
})
_id = {
"_id": f"$_id",
}

replaceRoot = {}

if len(parent) > 0:
replaceRoot = {
"$mergeObjects": [
"$doc",
{"_id": f"$_id._id"},
_merge_objects(parentRoot, parentAux.split("."), parentRoot, popAux)
]
}
else:
replaceRoot = {
"$mergeObjects": [
"$doc",
{"_id": "$_id._id"},

{popAux: f"${popAux}"}

]
}

aggregate.append({
"$replaceRoot": {"newRoot": replaceRoot}
})

# Generate a list of parents splitted by .
parents_list = parentAux.split (".")

# Lambda to generate the correct format
# For key its required to be with _ and for _id value is required a .
#e.g
# 'components': "$components._id",
# 'components_children': '$components.children._id'
formatted_parent = lambda c, limit: f"{c}".join (parents_list [0:limit + 1])

for i, _ in enumerate(parents_list):
idd = "$" + formatted_parent ('.', i) + "._id"
_id [formatted_parent ('_', i)] = idd

else:

_id = f"$_id"

# Group the path (The current populated item) in an array, if path has a dot, it means the populated item is inside an object
# Which doesn't care, so its required to take only the first name of the path.
"""
E.g.
for the schema:
users: [
{
user_id: {
type: Types.ObjectId,
required: True,
ref: "users"
},
count: {
type: Types.Number,
required: True
}
}
]
The path for populate would be /users.user_id/
"""

popAux = pop["path"]
if popAux.find(".") > 0:
popAux = popAux.split(".")[0]

group["_id"] = _id
group[popAux] = {"$push": f"${parent}{popAux}"}
group["doc"] = {"$first": "$$ROOT"}

# print (group)

# print (f"path: {pop['path']}")
# print (f"N_parents {n_parents}")
# print (f"Parent: {parentAux}")
# print (f"Was List: {wL}")

aggregate.append({
"$group": group
})

replaceRoot = {}

if len(parent) > 0:
replaceRoot = {
"$mergeObjects": [
"$doc",
{"_id": f"$_id._id"},
_merge_objects(parentRoot, parentAux.split("."), parentRoot, popAux)
]
}
else:
replaceRoot = {
"$mergeObjects": [
"$doc",
{"_id": "$_id._id"},

{popAux: f"${popAux}"}

]
}

aggregate.append({
"$replaceRoot": {"newRoot": replaceRoot}
})


return wasList

def _convert_id_to_object_id(id) -> ObjectId:
def _convert_id_to_object_id(id) -> ObjectId:#
if type(id) is not ObjectId:
id = ObjectId(id)
return id
Expand Down
4 changes: 2 additions & 2 deletions pymongoose/version.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
PYMONGOOSE_VERSION = "1.3.7"
PYMONGOOSE_VERSION_NAME = "Version 1.3.7"
PYMONGOOSE_VERSION = "1.3.8"
PYMONGOOSE_VERSION_NAME = "Version 1.3.8"
PYMONGOOSE_VERSION_AUTHOR = "Juan Carlos Lara"

def pymongoose_version_print_full():
Expand Down
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[metadata]
name = pymongoose
version = 1.3.7
version = 1.3.8
author = Juan Carlos Lara
author_email = [email protected]
description = A pymongo helper with methods and classes
Expand Down
2 changes: 1 addition & 1 deletion version.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.3.7
1.3.8

0 comments on commit 889efcc

Please sign in to comment.