0

I have a list of users in my mongodb database, which can then follow each other -pretty standard. Using php I want to check if a specific user is following another user. My data looks like this.

array (
  '_id' => ObjectId("56759157e1095db549d63af1"),
  'username' => 'Joe',
  'following' => 
  array (
    0 => 
    array (
      'username' => 'John',
    ),
    1 => 
    array (
      'username' => 'Tom',
    ),
  ),
)
array (
      '_id' => ObjectId("56759132e1095de042d63af4"),
      'username' => 'Tom',
      'following' => 
      array (
        0 => 
        array (
          'username' => 'Joe',
        ),
        1 => 
        array (
          'username' => 'John',
        ),
        2 => 
        array (
          'username' => 'Sam',
        ),
      ),
    )

I want a query that will check if Joe is following Sam (which he's not) - so it would produce no results. However, if I was to query the database to check if Tom was following Sam, then it would produce a result to indicate he is (because he is). Do you know how I would do this in PHP? I've experimented with Foreach loops, but I haven't been able to get the results I want.

Joe
  • 31
  • 5
  • Are the data you provided as example in one encompassing array, or did you just give two separate arrays as two different examples? If the first, it is best to add the separating comma half-way, and surround the whole lot with `array ( ... )`. – trincot Dec 19 '15 at 22:06
  • There are by an encompassing array. Apologise if it didn't appear that way. My plan is to expand and have a large amount of users, but you would put it in one array? – Joe Dec 19 '15 at 22:18
  • This sounds like a check you should make thru the database, not PHP –  Dec 19 '15 at 22:30
  • Please be aware that asking something about "Tom" can lead to unexpected results if you have several people named "Tom" (but with different IDs). Can you confirm that the names are unique? – trincot Dec 19 '15 at 22:45
  • Yes, so I used those names for simplification purposes - each would be a unique username. – Joe Dec 20 '15 at 00:05

2 Answers2

0

Make it by DB query, by php it will take more resources
Still if you want by php you can make it so

$following=false;
foreach($data as $v) if ($v['username'] == 'Joe') {
    foreach($v['following'] as $v1) if (in_array('Sam', $v1)) {
        $following=true;
        break 2;
    }
}
echo $following;
Max P.
  • 5,579
  • 2
  • 13
  • 32
0

Such queries are best done in SQL, but if you insist on a PHP-based solution I would suggest to turn the data structure into items keyed by name. Once you have that it is a piece of cake to find relationships:

function organisePersons($data) {
    $persons = array();
    foreach($data as $person) {
        $list = array();
        foreach($person["following"] as $following) {
            $list[$following["username"]] = $following["username"];
        }
        $person["following"] = $list;
        $person["followedBy"] = array();
        $persons[$person["username"]] = $person;
    }
    // link back to get all "followedBy":
    // You can skip this block if you don't need "followedBy":
    foreach ($persons as $person) {
        foreach($person["following"] as $following) {
            echo $person["username"] . " f. $following<br>";
            if (!isset($persons[$following])) {
                $persons[$following] = array(
                    "_id" => null, // unknown
                    "username" => $following,
                    "following" => array(),
                    "followedBy" => array()
                );
            }
            $persons[$following]["followedBy"][] = $person["username"];
        }
    }
    // return the new structure
    return $persons;
}

So first call the function above with the data you have:

$persons = organisePersons($data);

And then you can write this:

if (isset($persons["Joe"]["following"]["Sam"])) {
    echo "Joe is following Sam";  // not in output
};
if (isset($persons["Tom"]["following"]["Sam"])) {
    echo "Tom is following Sam";  // in output
};

But also:

echo "Tom is following " . implode($persons["Tom"]["following"], ", ");
// Output: Tom is following Joe, John, Sam

And even the reverse question "Tom is followed by who?":

echo "Tom is followed by " . implode($persons["Tom"]["followedBy"], ", ");
// Output: Tom is followed by Joe
trincot
  • 317,000
  • 35
  • 244
  • 286
  • Thanks for the response. What you've put is really useful, but it does suggest, as you pointed out, that maybe I'm trying to over engineer php. I originally went with this idea because I thought it would give me the flexibility to start adding values as I went along - such as relationship strength values that could be put in to algorithms. How would you suggest I structure the data in sql? A simple table with follower and followed? – Joe Dec 20 '15 at 01:27
  • In SQL you would have two tables, like `user(user_id, username, email)` and `relation(follower_user_id, followed_user_id, strength)`. This doesn't mean you should not use MongoDB. The more important thing is that you do queries directly on the database, instead of first loading all data in PHP and then querying that structure. – trincot Dec 20 '15 at 09:17