使用PHP驱动程序在文档中查找嵌套值

Okay so here is my issue. Each user in my db has field called 'friends'. Each time a friend is added, it gets a unique id and is also keyed in the friends field according to a string typed version of this id, like so:

$user          =   AppDatabase::getInstance()->getUser($user_id);
$user_friends  =   $user['friends'];
$new_friend    =   array
                                    (
                                        'friend_id'=>new MongoId($friend_id),
                                        'nickname'=>(string)$nickname,
                                        'friendpic'=>''
                                    );

$user_friends[(string)$friend_id] = $new_friend;

This is all good and works fine, I get a result in the db that looks like this:

'friends':
{
503da7ba65d351681a00000c
{
'friend_id':{$oid:503da7ba65d351681a00000c},
'nickname':"Heisenberg",
'friendpic':''
}
}

Now, what I need to be able to do is find a friend by only using their friend_id and not knowing the user_id (or anything about the user). I'm a little confused on how to do this, basically the process in my head is:

  • Pass in the friend's id
  • Query the user's collection
  • Find all "user_friends" fields
  • From this, find the key which matches the id I passed in originally
  • End up with the correct friend object

None of what I am trying really works though. Perhaps I have structured the data incorrectly. If someone could put me on the right path I'd really appreciate it.

Cheers!

Basically I think what you wanna do is create an edit form for, say, a friend that will span multiple users. So lets break this down:

  • You have the friend ID
  • All friends within all users have the same data (or maybe not and friend id is unique either way this should work)
  • You need to update that friend id without knowing the id of the root document

One thing that can help you here is v2.2 of Mongo which can actually pick this out using the positional operator from the main document giving you a similar result to:

'friends':
{
503da7ba65d351681a00000c: {
    'friend_id':{$oid:503da7ba65d351681a00000c},
    'nickname':"Heisenberg",
    'friendpic':'' }
}

Irrespective of how many friends you have in that list. I personally have not yet used this querying method however here is the JIRA for it: https://jira.mongodb.org/browse/SERVER-828 so you can play around however a query like:

find({'friends.503da7ba65d351681a00000c': {$exists: true}}, {'friends.$':1})

Might do the trick, I hear sometimes you need to use $elematch. I am unsure if this would totally work since I am not sure if friend_id is duplicated but still worth a try.

Pre 2.2 this is a little harder and as you say you must get out all friends where that friend id exists:

find({'friends.503da7ba65d351681a00000c': {$exists: true}});

And then go through that to pick them out (pseudo code):

foreach(result as id => friend){
    if(id == id_i_am_looking_for) return friend;
}

And then you can use that doc and update it. To place it back in the DB (providing you have the full object at hand) you can do:

db.update({'friends.503da7ba65d351681a00000c': {$exists: true}}, 
    {$set: {'friends.$' : new_friend_object}});

If you don't have the entire friends object to play with then you will need to update per field either way it is relatively the same.

After that you should now be able to update a friend without knowing the user_id.

Hope it helps,