beanie icon indicating copy to clipboard operation
beanie copied to clipboard

Query linked fields

Open joe-fitkey opened this issue 2 years ago • 2 comments

Hi there,

I have two documents a build and a deployment. A deployment has a build parameter that is a Link to a build document. Multiple deployments can be linked to the same build.

I now have two requirements:

  1. Get a list of all deployments for a build (the build _id is supplied)
  2. Get a list of all deployments that have a build where the project_name equals xyz.

I couldn't find any relevant sections in the docs.

Is this something Beanie has support for?

joe-fitkey avatar Dec 13 '21 14:12 joe-fitkey

Hi @joe-fitkey ,

  1. You can find by id with the next query:
from beanie import Document, Link

class Build(Document):
    ...

class Deployment(Document):
    build: Link[Build]
    
...

build_id = "YOUR BUILD ID"
deployments = await Deployment.find({"build.$id": build_id}).to_list()

$ there is not a typo. It uses RefID field type inside. I plan to add backward linking and syntax sugar for this find query later.

  1. Unfortunately, this is possible with lookup aggregations only for now. Here is the MongoDB doc for lookups: https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/ Here is the Beanie doc for aggregations: https://roman-right.github.io/beanie/tutorial/aggregation/

Find by fields of the linked documents is one of the most important features to develop for now. It is estimated to be done in 2-3 weeks. I'll inform you here when it will be done.

roman-right avatar Dec 13 '21 14:12 roman-right

Seems like there was an initial go at getting this working recently. But the documented approach doesn't seem to work for me.

Using the above example my code would be something like

Deployment.find(Deployment.build.id == build_id, fetch_links=True)

This doesn't seem to work. I've tried what you mentioned as well with the {"build.$id": build_id} however this only works if you do NOT specify fetch_links

mdgilene avatar Jan 27 '22 17:01 mdgilene

The docs claim that this works but I also find that it does not

gegnew avatar Jan 17 '23 19:01 gegnew

Okay, I spent some more time with this, and it does seem to be the case that the documented behavior is not accurate. I am unable to query for a document by the properties of it DbRef, despite this apparently being supported. Any ideas as to why? My setup is basically:

# the base classes just define properties shared with the API schema objects

class Device(Document, DeviceBase):
    name: Optional[str] = ""

class Package(Document, PackageBase):
    tracking_number: Indexed(str, unique=True)  # type: ignore
    device: Link[Device]

device_ids = ['id1', 'id2', 'id3']

packages = await Package.
	In(Package.device.id, device_ids), 
	fetch_links=True,
).to_list()

# packages returns []

# I've also tried i.e.:

packages = await Package.
	Package.device.id == 'id1', 
	fetch_links=True,
).to_list()

packages = await Package.
	Package.device.id == Device1.id, 
	fetch_links=True,
).to_list()


packages = await Package.
	Package.device == Device1, 
	fetch_links=True,
).to_list()

gegnew avatar Jan 18 '23 16:01 gegnew

This issue is stale because it has been open 30 days with no activity.

github-actions[bot] avatar Feb 26 '23 02:02 github-actions[bot]

This issue was closed because it has been stalled for 14 days with no activity.

github-actions[bot] avatar Mar 13 '23 02:03 github-actions[bot]

same issue here.

This works

app = await App.get(str(app_id))

# check if app exists

query = await QueryDoc.find({ "app.$id": app_id}).to_list(limit)

but these don't

query = await QueryDoc.find(QueryDoc.app == app.id).to_list(limit)

query = await QueryDoc.find(QueryDoc.app == app).to_list(limit)

gianpaj avatar Jan 10 '24 13:01 gianpaj