Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Selective Hydration #1020

Closed
renatomefi opened this issue Jan 28, 2015 · 10 comments
Closed

Selective Hydration #1020

renatomefi opened this issue Jan 28, 2015 · 10 comments
Labels

Comments

@renatomefi
Copy link

Hello,

I'm using mongodb within an api, when I'm using hydrating to get a value this is my response:

{
    "id": "54c8ca42eabc88400d8b4568",
    "language": {
        "id": "54b7bf0654064d33048b456d",
        "last_update": {
            "sec": 1421328134,
            "inc": 2
        },
        "key": "pt-br",
        "translations": {
           ...
           ...
           ...
           ...
           ...
           ...
           "Lots of infos"
        }
    },
    "key": "pt-br-key-test-4",
    "value": "pt-br-value-test-4"
}

When the hydrate is false I get rid of the lot of infos, but my id is now "protected" as _id.
Is there a way to hydrate only some references? And why id is a reference? Is it a mongodb way of work?

{
    "_id": {
        "$id": "54c8ca42eabc88400d8b4568"
    },
    "key": "pt-br-key-test-4",
    "language": {
        "$ref": "Language",
        "$id": {
            "$id": "54b7bf0654064d33048b456d"
        },
        "$db": "angular_symfony"
    },
    "value": "pt-br-value-test-4"
}

Another thing that I was thinking about, is there a way to choose the depth of hydration? The main reason that I'm not hydrating this query is because of crossed references bringing more data that I want, if I was able to choose only 1 level of depth this would be great!

Thank you

@renatomefi
Copy link
Author

Is there any other solution to achieve the same result?

@malarzm
Copy link
Member

malarzm commented Apr 23, 2015

When the hydrate is false I get rid of the lot of infos, but my id is now "protected" as _id.

This is how field is named in db and since hydration is disabled you are getting data in a way it is in database (but it is kind of protected since its value can't be changed in db

Is there a way to hydrate only some references?

Not sure if that's what you meant, but you can select only certain fields to be fetched using $qb->select()

And why id is a reference?

It is not, if you take a look in the database you will see that _id has value of ObjectId("xxxxxxx") and

    "_id": {
        "$id": "54c8ca42eabc88400d8b4568"
    }

is just a way it's serialized from there.

Another thing that I was thinking about, is there a way to choose the depth of hydration?

I'm afraid there is no such functionality in ODM

Is there any other solution to achieve the same result?

I think that the best is selective query and manual preparation for serialization during which you will get rid of unwanted fields. If you are not using it already take a look at https://github.com/schmittjoh/serializer (and https://github.com/schmittjoh/JMSSerializerBundle if you are using Symfony)

@renatomefi
Copy link
Author

Hello @malarzm, thanks for the answer!

I was trying some solutions but I had no success, look at my query:

        $result = $dm
            ->createQueryBuilder('FormBundle:Protocol')
            ->hydrate(true)
            ->select('id', 'createdAt')
            ->field('id')->equals($protocol->getId())
            ->getQuery()
            ->getSingleResult();

Debugging the query:

db.Protocol.find({ "_id": ObjectId("55427c1578a3245b048b456e") }, { "_id": 1, "createdAt": 1 }).limit(1).limit();

It should return this:

{
  "id":"554278e078a3245b048b456a",
  "created_at": 2015-04-30T18:48:00.025Z"
}

But since I used the hydrate it returned everything:

{
    "comment": [],
    "created_at": {
        "sec": 1430420501,
        "usec": 538000
    },
    "field_values": [],
    "file": [],
    "form": {
        "created_at": "2015-04-30T11:59:44-0300",
        "fields": [
            {
                "created_at": "2015-04-30T11:59:45-0300",
                "id": "5542436178a3249e0b8b45b3",
                "name": "1_1",
                "options": {
                    "estadual": "Estadual",
                    "federal": "Federal"
                }
            },
            ......... many, many items
            {
                "created_at": "2015-04-30T11:59:45-0300",
                "id": "5542436178a3249e0b8b4803",
                "name": "23_10"
            }
        ],
        "id": "5542436078a3249e0b8b459a",
        "name": "inspecao-estabelecimentos-penais",
        "pages": [
            {
                "created_at": "2015-04-30T11:59:44-0300",
                "id": "5542436078a3249e0b8b459b",
                "number": 1,
                "title": "Estrutura Organizacional"
            },
            ......... 22 items
            {
                "created_at": "2015-04-30T11:59:44-0300",
                "id": "5542436078a3249e0b8b45b2",
                "number": 24,
                "title": "Valora\u00e7\u00e3o sobre os itens inspecionados"
            }
        ],
        "template": "inspecao-estabelecimentos-penais"
    },
    "id": "55427c1578a3245b048b456e",
    "non_user": [],
    "user": []

Is is the right behavior?
When the hydrate is false it will respect the select fields.

Thank you again

@malarzm
Copy link
Member

malarzm commented May 4, 2015

@renatomefidf was the queried object fetched before the selective query?

@lalop
Copy link

lalop commented May 4, 2015

Hi,
Not sure but I think you can define a new entity querying the same Collection and hydrating only the field you need for your api.

@renatomefi
Copy link
Author

@malarzm I believe not, how can I check it?

@renatomefi
Copy link
Author

@lalop I have no idea how to do this, can you guide me?

@lalop
Copy link

lalop commented May 4, 2015

@renatomefidf http://docs.doctrine-project.org/projects/doctrine-mongodb-odm/en/latest/reference/basic-mapping.html#persistent-classes
You can define 2 entity with the same collection but differents fields

<?php

namespace Documents;

/** @Document(db="my_db", collection="users") */
class User
{
}
<?php

namespace Documents;

/** @Document(db="my_db", collection="users") */
class ApiUser
{
}

In the ApiUser class you can define only the field that you want for api

@malarzm
Copy link
Member

malarzm commented May 4, 2015

@renatomefidf if you have queried for the object before, UnitOfWork will return already fetched (hydrated) object even when using Query and QueryBuilder alone unless refresh() was used

@malarzm
Copy link
Member

malarzm commented Jul 30, 2016

Closing since the question has been answered and no further update from @renatomefidf was received

@malarzm malarzm closed this as completed Jul 30, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants