0

I am using Laravel with jenssegers Mongodb Eloquent. When I try to use get([...]) or distinct('...') it gives null values in the result. How can I use get([eager_loaded_attribute_here]) to get only a given attribute that was eager-loaded?

Example:

Message::with(['sender','receiver'])
    ->where('sender_id', '=', Auth::user()->_id)
    ->orWhere('receiver_id', '=', Auth::user()->_id)
    ->orderBy($request->orderBy, $request->orderByDirection)
    ->skip(intval($request->offset))
    ->take(intval($request->limit))
    ->get()

Gives:

[
    {
        "_id": "5abc2ba193782d24996aefda",
        "receiver_id": "5abc28bd93782d235238c162",
        "text": "Hello!",
        "sender_id": "5abc2b8b93782d24996aefd8",
        "updated_at": "2018-03-28 23:56:17",
        "created_at": "2018-03-28 23:56:17",
        "sender": {
            "_id": "5abc2b8b93782d24996aefd8",
            "name": "Test 5",
            "updated_at": "2018-03-29 00:05:48",
            "created_at": "2018-03-28 23:55:55"
        },
        "receiver": {
            "_id": "5abc28bd93782d235238c162",
            "name": "Test 1",
            "updated_at": "2018-04-20 13:26:00",
            "created_at": "2018-03-28 23:43:57"
        }
    },
...
]

But using get:

Message::with(['sender','receiver'])
    ->where('sender_id', '=', Auth::user()->_id)
    ->orWhere('receiver_id', '=', Auth::user()->_id)
    ->orderBy($request->orderBy, $request->orderByDirection)
    ->skip(intval($request->offset))
    ->take(intval($request->limit))
    ->get(['sender'])

Gives:

[
    {
        "_id": "5abc2ba193782d24996aefda",
        "sender": null,
        "receiver": null
    },
...
]

Likewise, when using distinct:

$correspondants=Message::with(['sender','receiver'])
    ->distinct('sender_id')
    ->where('sender_id', '=', Auth::user()->_id)
    ->orWhere('receiver_id', '=', Auth::user()->_id)
    ->orderBy($request->orderBy, $request->orderByDirection)
    ->skip(intval($request->offset))
    ->take(intval($request->limit))
    ->get()
    ->toArray();

Gives:

[
    {
        "0": "5abc2b8b93782d24996aefd8",
        "sender": null,
        "receiver": null
    }
]
Jonas Staudenmeir
  • 24,815
  • 6
  • 63
  • 109
Daniel Valland
  • 1,057
  • 4
  • 21
  • 45
  • What are you trying to achieve? – Jonas Staudenmeir May 13 '18 at 13:18
  • @JonasStaudenmeir I am trying to select a field that is eager-loaded. I only need sender to be returned, so ideally I would like to "un-nest" sender from it's parent object, and return only an array of senders... Ideally I would also like to be able to perform further queries on the senders, much like an SQL select (projection). But when I use select on an eager-loaded field, I get only null... Are there any alternatives to get(...) that returns a querybuilder, so I can continue chaining on further queries? thanks.. – Daniel Valland May 14 '18 at 15:01
  • If you don't need `receiver`, you should just use `with('sender')`. – Jonas Staudenmeir May 14 '18 at 15:06
  • @JonasStaudenmeir yep, but it was just to show that for some reason, other eager-loaded fields are affacted... In that case, I expected to get only the sender field, but got both eager-loaded fields with null values for some reason... – Daniel Valland May 14 '18 at 15:07

1 Answers1

0

Use this:

->get()->pluck('sender');

If you need a query builder:

$senderIds = Message::distinct('sender_id')
    ->where('sender_id', '=', Auth::user()->_id)
    [...]
    ->pluck('sender_id');
$senders = Sender::whereKey($senderIds)
    [...]
    ->get();
Jonas Staudenmeir
  • 24,815
  • 6
  • 63
  • 109
  • Great, and is there a way I can get it to return a querybuilder such that I can continue chaining on queries (for example orderBy, take etc..)? – Daniel Valland May 14 '18 at 15:05
  • I extended my answer. – Jonas Staudenmeir May 14 '18 at 15:10
  • Thanks a lot... Is this safe for large collections? It looks like it is fetching all sender id's, which would be safe if take/limit is performed on the first query (senderIds), but I suppose this would be rather unsafe if there was a large amount of senderIds (ex: 10m), and take/limit needed to be done in the second query (for $senders), but not the first? – Daniel Valland May 14 '18 at 15:15
  • In the first query `[...]` represents your `take()` and `skip()` calls etc. I just wanted to keep it short and focus on the relevant parts. – Jonas Staudenmeir May 14 '18 at 15:21