0

I would like to get a user from the database. My function takes in a requesterId which is the ID of the user requesting this data, and a targetId which is the user to retrieve.

If the requester is in the target's friends array (strings), the phone field should be included in the projection. If not, it is excluded.

I have come up with the following query after reading the example here. However, the phone field is always returned no matter what. What am I doing wrong?

  getUser: function getUser(requesterId, targetId) {
    return db.collection('users').aggregate([
      {$match: {userId: targetId}},
      {
        $project:
          {
            firstName: 1,
            phone: {
              $cond: {
                if: {friends: requesterId},
                then: "$phone",
                else: "$$REMOVE"
              }
            }
          }
      },
      {$limit: 1}
    ]).toArray();
  }

Schema (created in Compass so no code):
userId - String
firstName - String
friends - Array(String)
phone - String

Indices: None on this collection

Example:

/* Bob's MongoDB data */ {userId: "BobID", firstName: "Bob", friends: ["AmyID"], phone: "1234567890"}
getUser(requesterId = 'AmyID', targetId = 'BobID');
/* Result */ {firstName: "Bob", phone: "1234567890"}

/* Amy's MongoDB data */ {userId: "AmyID", firstName: "Amy", friends: ["CassieID"], phone: "9876543210"}
getUser(requesterId = 'BobID', targetId = 'AmyID');
/* Result */ {firstName: "Amy", phone: "987654321"}

Bob's request for Amy's user should not return her phone number because he is not in her friends array.

JohnnyHK
  • 305,182
  • 66
  • 621
  • 471
Matt
  • 2,953
  • 3
  • 27
  • 46
  • use `$filter` aggregation. https://stackoverflow.com/questions/3985214/retrieve-only-the-queried-element-in-an-object-array-in-mongodb-collection – Ashh Sep 29 '18 at 13:11
  • Can you post the schemas? – Ahmed Agiza Sep 29 '18 at 13:12
  • @AnthonyWinzlet I'm unclear as to how`$filter` will help here. I'm not trying to get any results from the `friends` array, I would just like to check that the parameter is in that array so I can include or exclude an entirely separate field. – Matt Sep 29 '18 at 13:18
  • ok could you post sample data – Ashh Sep 29 '18 at 13:20

1 Answers1

1

The if: value must be a boolean expression, not a query object. To check whether a specified value is in an array, you can use the $in expression:

db.collection('users').aggregate([
  {$match: {userId: targetId}},
  {
    $project:
      {
        firstName: 1,
        phone: {
          $cond: {
            if: {$in: [requesterId, '$friends']},
            then: "$phone",
            else: "$$REMOVE"
          }
        }
      }
  },
  {$limit: 1}
])
JohnnyHK
  • 305,182
  • 66
  • 621
  • 471