How to set array response in api-doc? - api-doc

I tried to generate a API document by apidoc
If my response is a array like
[
{"id" : 1, "name" : "John"},
{"id" : 2, "name" : "Mary"}
]
How could I set in #apiSuccess?
I had try Object[] but did not know how to set the field name.
Thanks.

Lets say in the above example the id and name are of a user-profile, and you have an array of user-profile objects, then the #apiSuccess will look like:
/**
* #api {get} /users
* #apiSuccess {Object[]} profiles List of user profiles.
* #apiSuccess {Number} profiles.Id Users id.
* #apiSuccess {String} profiles.Name Users Name.
*/

Related

GraphQL Dataloader fails if backend returns null values

I have a GraphQL object type Student. And each student may or may not have Phone data.
Phone is another GraphQL type object (A child object in Student).
I have GraphQL dataloader registered on Phone. Things work fine as long as each student record has a corresponding Phone record. But if there is any student record who does not have a corresponding phone record, Dataloader fails with error:
"message": "Exception while fetching data (/students[0]/phone) : The size of the promised values MUST be the same size as the key list",
I believe this is because, dataloader is trying to assert that size-of-keys-in-list should be same as size-of-values-resolved-in-list.
Is there anyway to accept null as values which is a valid case in my requirement.
Found that the backend server is not even sending 'null', it just ignores the missing record.
From official source:
https://github.com/graphql-java/java-dataloader/blob/7bf46ea182b1f8ab255c3107b1b61d4afd36ad88/src/main/java/org/dataloader/BatchLoader.java
Dataloader does support null values:
*
* <pre>
* [
* { id: 2, name: 'San Francisco' },
* { id: 9, name: 'Chicago' },
* null,
* { id: 1, name: 'New York' }
* ]
* </pre>

I want to update values ​in an array in an array while using MongoTemplate

First, I will show the state stored in mongodb.
As you can see, it is a structure with a list called replies in a list called comments. And inside replies there is an array called likes.
comments : [
Object1 : {
replies : [
likes : [
0 : {},
1 : {}
]
]
},
Object2 : {
replies : [
likes : [
0 : {},
1 : {}
]
]
}
]
What I want to do here is to insert/subtract a value only from the likes array inside a specific replies structure. I'm currently using Spring boot and have tried the following:
Query query = new Query();
Criteria criteria = Criteria.where("_id").is(new ObjectId(postId))
.andOperator(Criteria.where("comments")
.elemMatch(Criteria.where("_id").is(new ObjectId(commentId))
.andOperator(Criteria.where("replies")
.elemMatch(Criteria.where("_id").is(new ObjectId(replyId)))
)
)
);
query.addCriteria(criteria);
Update update = new Update();
if (state) {
// remove user id
update.pull("comments.$[].replies.$.likes", new ObjectId(userId));
} else {
// add user id
update.push("comments.$[].replies.$.likes").value(new ObjectId(userId));
}
mongoTemplate.updateFirst(query, update, MyEntity.class);
It is an operation to add or remove userId according to boolean state. As a result of the attempt, up to a specific comment is found, but userId is unconditionally entered in the first likes list of the replies list inside the comment. What I want is to get into the likes list inside a specific reply. Am I using the wrong parameter in update.push()? I would appreciate it if you could tell me how to solve it.
Not a direct answer to your question as I'm not experienced with spring's criteria builder, but here's how you would do it in mongo directly, which might help you to figure it out:
You could define arrayfilters allowing you to keep track of the corresponding indices of each comments and replies. You can then use those indices to push a new object at the exact matching indices:
db.collection.update({
_id: "<postId>"
},
{
$push: {
"comments.$[comments].replies.$[replies].likes": {
_id: "newlyInsertedLikeId"
}
}
},
{
arrayFilters: [
{
"comments._id": "<commentId>"
},
{
"replies._id": "<replyId>"
}
]
})
Here's an example on mongoplayground: https://mongoplayground.net/p/eNdDXXlyi2X

Is the schemas section in the nelmio_api_doc.yaml required?

I have been setting up the Nelmio API Doc Bundle with Swagger-PHP. All is working as expected the only thing I cannot seem to figure out/understand is the schemas.
In the User controller I have the following annotation:
* #OA\RequestBody(
* description="Updated user object",
* required=true,
* #OA\MediaType(
* mediaType="multipart/form-data",
* #OA\Schema(ref="#/components/schemas/User")
* )
* )
In my Entity/User class I defined the schema as follows:
/**
* User
*
* #OA\Schema(schema="User")
*
* #ORM\Table(schema="app", name="users")
* #ORM\Entity
*/
class User implements UserInterface
In the User controller I have the use App\Entity\User; defined as well.
In my mind this would be enough for the schema to be found but it doesn't work as I would otherwise not be posting here :)
The only way I was able to make it work is to run vendor/bin/openapi --format yaml src and copy/paste the schema output into the nelmio_api_doc.yaml file. This is the schema part I copy/pasted:
User:
properties:
first_name:
type: string
middle_name:
type: string
last_name:
type: string
initials:
type: string
username:
type: string
password:
type: string
status:
type: integer
email:
type: string
id:
type: integer
customer_id:
type: integer
locked:
type: boolean
type: object
So my question is, is this the way to about it or should the schema section be created automatically?
Thanks for any insights.
NelmioApiDocBundle does not load all files to fetch annotations in opposition to swagger-php, to load a schema, you should use the #Model annotation, see https://symfony.com/doc/current/bundles/NelmioApiDocBundle/index.html#use-models.
In your case, that would give the following:
use Nelmio\ApiDocBundle\Annotation\Model;
/**
* #OA\RequestBody(
* description="Updated user object",
* required=true,
* #OA\MediaType(
* mediaType="multipart/form-data",
* #OA\Schema(ref=#Model(type=User::class))
* )
* )
*/

Type of return data in API platform

I have a problem of changing types of returned data in API platform:
I have an entity:
final class ModelClass
{
/**
* #var float
*/
public $total;
}
And a configuration:
ModelClass:
properties:
total:
attributes:
swagger_context:
type: float
And Controller:
public function __invoke(CustomRequest $request): Paginator
{
return $this->service->getTotals($request);
}
The return of this is Paginator, which holds custom doctrine query, result of which looks like this:
{
"#type": "hydra:Collection",
"hydra:member": [
{
"id": 1,
"total": "120.00",
},
]
}
As you see, total is a string (because in the result of query it is a string). What i want it to be: a float: "total": 120.00. And what i would also like to be able to do, is to format it differently, for example separator sign ',' instead '.'
I didnt find in documentation how to do it. Is it a missing documentation or missing feature?
I would expect that API platform reads DocBlock to understand the type of Model. And i think that there is some intercept mechanism after query is executed, but before response is sent back to client, so i could change format/type.
Thank you.

MongoDB embedded document BSON ID

I have a webapp where I'm created an embedded document for educations. The job document looks something like this:
"educations" : [
{
"school" : "Brandywine High School",
"major" : "Testingasdf",
"grad_year" : ISODate("1979-01-01T00:00:00Z"),
"school_type" : "Graduate",
"_id" : ObjectId("4fb26c9ce5be08208b000ce4")
}
],
"email" : "user#domain.com",
The education hash has the details of the job. I noticed that if i create the hash without an ID:
User.collection.update(
{ _id: #user.id },
{ :$push => { educations: education } },
{ safe: true }
)
and I query the education from the Rails console, the ID will change each time:
irb(main):004:0> User.brandon.educations.map(&:id)
=> [BSON::ObjectId('4fb26e13e5be082384000007')]
irb(main):005:0> User.brandon.educations.map(&:id)
=> [BSON::ObjectId('4fb26e13e5be082384000009')]
However, if I do this:
User.collection.update(
{ _id: #user.id },
{ :$push => { educations: BSON::ObjectId.create_pk(education) } },
{ safe: true }
)
The ID is the same each time queried from the console. Because of this, I'm having trouble referencing the education to edit the embedded doc in the browser.
Do I always have to supply a BSON ID when I create an embedded document?
If you don't supply some kind of identifier (it could be a String, an int, etc) in the _id field, then MongoDB will automatically create one for you, to make the document unique (so that it can be looked up by _id). There is normally a unique index on _id, so if the document isn't unique, insertion will fail (or the existing document will be updated instead, etc).
MongoDB's strategy for making the document unique is to use an ObjectID, as these are globally unique. They are also different every time you create one — that's how they are globally unique.
Long story short: if you have a key that makes your document 100% unique already (possibly :school in your example), then store it as _id, and MongoDB will do the hard work for you.

Resources