How do I query MongoDB collection based on related documents (in Doctrine) - mongodb

I have a few related collections in my Doctrine ODM project…
# Contract.mongodb.yml
Project\Contract\Domain\Contract:
type: document
repositoryClass: Project\SymfonyBundle\ContractBundle\Repository\ContractRepository
collection: Contracts
fields:
id:
type: id
id: true
strategy: UUID
slug:
type: string
length: 128
unique: true
gedmo:
slug:
separator: -
style: default
fields:
- refNo
- name
name:
type: string
refNo:
type: string
purpose:
type: string
budgetAmount:
type: int
budgetCurrency:
type: string
length: 3
startDate:
type: date_immutable
endDate:
type: date_immutable
provider:
type: string
referenceOne:
provider:
targetDocument: Project\Contract\Domain\Provider
cascade:
- persist
- merge
- detach
- refresh
referenceMany:
reports:
targetDocument: Project\Report\Domain\Report
cascade:
- all
# Provider.mongodb.yml
Project\Contract\Domain\Provider:
type: document
repositoryClass: Project\SymfonyBundle\ContractBundle\Repository\ProviderRepository
collection: Providers
fields:
id:
type: id
id: true
strategy: UUID
slug:
type: string
length: 128
unique: true
gedmo:
slug:
separator: -
style: default
fields:
- name
name:
type: string
unique: true
referenceMany:
users:
targetDocument: Project\User\Domain\User
cascade: []
# User.mongodb.yml
Project\User\Domain\User:
type: document
repositoryClass: Project\SymfonyBundle\UserBundle\Repository\UserRepository
collection: Users
fields:
id:
type: id
id: true
strategy: UUID
What I want to do is get the contracts for a given user, but I can't work out how to query the Contracts collection based on a user. Do I need to make 2 queries? 1 to get the user's providers & then a second to query for contracts that link to one of the providers?
If you're able to advise how I do this in the console as well as Doctrine, I'd appreciate the knowledge.
Thanks in advance for your help :o)

You can use the aggregation pipeline and use the $lookup operator to join the document, See - https://docs.mongodb.com/v3.2/reference/operator/aggregation/lookup/
However if this is common, I'd consider re-modeling your documents.

Related

Specify Dynamic keys in openapi yaml

I want to create a response structure like this where either fieldProfile (profile type) or summaryProfile is optional. i.e outer key is dynamic and optional
{
"fieldProfile": [
"metric1",
"metric2",
"metric3"
],
"summaryProfile": [
"metric1",
"metric2",
"metric3"
]
}
Or
{
"fieldProfile": [
"metric1",
"metric2",
"metric3"
]
} // Here Summary Profile is removed, similarly we can have a response of summaryProfile or have both in response
I am creating the response schema like this, but here I want the metricType (fieldProfile/summaryProfile) to be the key for metrics (metric list).
ProfileMetrics:
description: List of metrics available in Field Profile
type: object
required:
- metricType
- metrics
properties:
metrics:
type: array
items:
type: object
required:
- metricName
properties:
metricName:
type: string
Any help is appreciated
Your schema can be defined as follows:
MySchema:
type: object
properties:
fieldProfile:
type: array
items:
type: string
summaryProfile:
type: array
items:
type: string
# At least fieldProfile or summaryProfile (or both) must be present
minProperties: 1
Instead of minProperties: 1, you can use this anyOf + required construct, it will achieve the same effect in this example:
anyOf:
- required: [fieldProfile]
- required: [summaryProfile]

Where to define reusable subschemas in OpenAPI 3?

I'm working on OpenAPI 3 document. I have schema called CustomerInfo: that has property Address. One of the properties of Address is enum called State. How do I make State a reusable property that can be referenced in other parts of CustomerInfo ?
components:
schemas:
CustomerInfo:
type: object
properties:
Address:
type: object
description: Contains the street, city, zip, and state associated with an address.
properties:
State:
$ref: ''
required:
- Street1
- State
I was thinking about defining a State under definitions: within CustomerInfo, but https://editor.swagger.io/ is throwing exception :
components:
schemas:
CustomerInfo:
type: object
properties:
Address:
type: object
description: Contains the street, city, zip, and state associated with an address.
properties:
State:
$ref: '#/components/schemas/CustomerInfo/definitions/State'
required:
- Street1
- State
definitions:
State: ....
Put the schema of State under components/schemas and it can be referenced.
components:
schemas:
CustomerInfo:
type: object
properties:
Address:
type: object
description: Contains the street, city, zip, and state associated with an address.
properties:
State:
$ref: '#/components/schemas/State'
required:
- State
State:
type: string
enum:
- Alabama
- Alaska
- Arizona

How to use the same definition for an ID parameter and an ID schema property?

I am wondering if there is a way in OpenAPI to describe that the user_id used as a path parameter is the same type of value as the id field of a User object. A benefit of this is reusing the description and example.
openapi: 3.0.1
info:
title: Test API
version: 1.0.0
paths:
/foo/{user_id}:
get:
parameters:
- $ref: '#/components/parameters/user_id'
responses:
'200':
description: A user
content:
application/json:
schema:
$ref: '#/components/schemas/User'
components:
parameters:
user_id:
name: user_id
in: path
required: true
description: the id of a User, from parameters
example: ghijkl
schema:
type: string
schemas:
User:
type: object
properties:
id:
type: string
description: the id of a User, from schemas
example: abcdef
I don't like having to re-define the example and description of the user ID.
You can define a separate schema for the user ID and have the parameter/property schema reference the user ID schema:
components:
parameters:
user_id:
name: user_id
in: path
required: true
schema:
$ref: '#/components/schemas/UserId' # <-------
schemas:
UserId:
type: string
description: The ID of a User
example: abcdef
User:
type: object
properties:
id:
$ref: '#/components/schemas/UserId' # <-------
Swagger Editor and Swagger UI will fetch the parameter example from the schema example, but the parameter description is currently not fetched from the schema description. Feel free to submit an enhancement request.

openapi 3.0 - change from array to dictionary/hashmap

This is basically the inventory example from Swagger Hub with a few items changed inside the array. Here is what the response looks like when I make a Python request to my SwaggerHub URL:
[{
"hostname": "server",
"ip_addr": "192.168.0.12",
"app_name": "generic",
"app_code": 12345678,
"xmx": "5678",
"jvm_version": "1.0.0",
"xms": "1234"
}]
How can I change the code so that it's a dictionary? I can't believe how many lines of YAML it takes to do what Flask or Falcon can do in about 5 lines of code.
Anyways, here is the template:
openapi: 3.0.0
# Added by API Auto Mocking Plugin
servers:
- description: SwaggerHub API Auto Mocking
url: https://virtserver.swaggerhub.com/james_test/test/1.0.0
info:
description: This is a simple API
version: "1.0.0"
title: Simple Inventory API
contact:
email: you#your-company.com
license:
name: Apache 2.0
url: 'http://www.apache.org/licenses/LICENSE-2.0.html'
tags:
- name: admins
description: Secured Admin-only calls
- name: developers
description: Operations available to regular developers
paths:
/data:
get:
tags:
- developers
summary: get random data from james_test API
operationId: searchInventory
description: |
By passing in the appropriate options, you can search for
available inventory in the system
responses:
'200':
description: search results matching criteria
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/state_data'
'400':
description: bad input parameter
components:
schemas:
state_data:
type: object
required:
- app_code
- app_name
- jvm_version
- hostname
- ip_addr
- xms
- xmx
properties:
app_code:
type: integer
format: int64
example: 12345678
app_name:
type: string
example: generic
jvm_version:
type: string
format: string
example: '1.0.0'
hostname:
type: string
format: hostname
example: 'server'
ip_addr:
type: string
format: ipv4
example: '192.168.0.12'
xms:
type: string
format: string
example: '1234'
xmx:
type: string
format: string
example: '5678'
Thank you all.
Edit:
I was hoping to get the response like this:
{
"hostname": "server",
"ip_addr": "192.168.0.12",
"app_name": "generic",
"app_code": 12345678,
"xmx": "5678",
"jvm_version": "1.0.0",
"xms": "1234"
}
SwaggerHub mock server returns an array because your response is defined as an array:
content:
application/json:
schema:
type: array # <----
items:
$ref: '#/components/schemas/state_data'
To get an object response, use:
content:
application/json:
schema:
$ref: '#/components/schemas/state_data'

Can we use allOf in OpenAPI /components/parameters to override attributes of a referenced parameter?

I am trying to create API documentation using OpenAPI 3 but I get errors when I'm trying to use the allOf keyword in a parameter definition:
components:
parameters:
idParam:
name: id
in: path
description: ID of the boxx
required: true
schema:
type: string
format: int65
dataSourceID:
allOf:
- $ref: '#/components/parameters/idParam'
- name: dataSourceID
description: ID of the data source
Schema error at components.parameters['dataSourceID']
should NOT have additional properties
additionalProperty: allOf
Is is possible to reuse the values of another parameter? Maybe in a different way?
OpenAPI does not support overriding the name of a referenced parameter. Here's a related feature request in the OpenAPI Specification repository:
Extend/override properties of a parameter
In OpenAPI 3.1, however, it's possible to override the description of a referenced parameter:
# openapi: 3.1.0
components:
parameters:
...
dataSourceID:
$ref: '#/components/parameters/idParam'
description: ID of the data source # <--- supported
# name: dataSourceID # <--- not supported
In your example, the most you can do is define a reusable schema for int65 and reference it from both parameters:
openapi: 3.0.0
...
components:
schemas:
int65:
type: string
format: int65
parameters:
idParam:
name: id
in: path
description: ID of the boxx
required: true
schema:
$ref: '#/components/schemas/int65' # <-----
dataSourceID:
name: dataSourceID
in: path
description: ID of the data source
required: true
schema:
$ref: '#/components/schemas/int65' # <-----
I guess allOf can be used in parameters schema as below.
allOf can be used in schema objects only.
And since parameters,paths may contain schema objects allOf can be used in parameters as follows.
components:
parameters:
idParam:
name: id
in: path
description: ID of the boxx
required: true
schema:
type: string
format: int65
dataSourceID:
name: dataSourceID
in: path
description: dataSourceID of the boxx
schema:
allOf:
- $ref: '#/components/parameters/idParam'
- type: object
properties:
name:
type: string
description:
type: string