0

I'm using mongodb with this collections: User and Follow. User collection has users and follow has the followers mapping.

Try to run this query but only get the user's followers and who I'm following too:

users = User.collection.aggregate([{
    "$lookup": {
      from: "follows",
      localField: "_id",
      foreignField: "followable_id",
      as: "follow"
    }
  },
  {
    "$match": {
      "follow.followable_type": "User",
      "follow.user_id": BSON::ObjectId.from_string(userid)
    }
  },
  {
    "$group": {
      _id: "$follow.followable_id",
      count: {
        "$sum": 1
      },
      data: {
        "$addToSet": "$$ROOT"
      },
    }
  },
  {
    "$project": {
      _id: 1,
      data: 1,
      count: 1,
      follow: {
        '$cond': {
          'if': {
            '$eq': ["$count", 2]
          },
          then: true,
          else: false
        }
      }
    }
  },
  {
    "$skip": 0 * 10
  },
  {
    "$limit": 10
  }
])

  users.each do |user|
    puts "#{user['data'].first['name']}: #{user['follow']}: #{user['count']}"
  end

How to return in the same query the users I'm following?

the output:

  Diego_Lukmiller: false: 1
  Marianno: false: 1
  kah: false: 1
  Fausto Torres: false: 1
fct
  • 311
  • 3
  • 18
  • put your sample collection and the output please... By seeing your query we would not be able to know what you want to achieve here – Ashh Aug 16 '18 at 06:17
  • @AnthonyWinzlet output added. The query returns followers of certain user. In the same query need to mark the users I also follow. – fct Aug 16 '18 at 06:51
  • this might help you https://stackoverflow.com/questions/50385075/add-fields-where-condition-match-to-nested-array... – Ashh Aug 16 '18 at 08:15

1 Answers1

0

I solved/fixed it by doing in three steps (written in ruby/mongoid):

  //get users the user X follows
  users = Follow.collection.aggregate([
    { "$match": { "followable_id": BSON::ObjectId.from_string(userid) } },
    { "$lookup": { from: "users", localField: "user_id", foreignField: "_id", as: "user" } },
    { "$unwind": "$user" },
    { "$sort": {"created_at":-1} },
    { "$skip": page * 10 },
    { "$limit": 10 },
    { "$group":{ _id: "$followable_id", data: {"$addToSet": "$user._id"} } }
  ])
  userids=users.blank? ? [] : users.first['data'].to_a

  //get users I follow
  f=Follow.collection.aggregate([
    {"$match":{user_id: BSON::ObjectId.from_string(meid), followable_id: {"$in":userids}}},
    {"$group":{ _id: nil, data: {"$addToSet": "$followable_id"}}}
  ])

  //make intersection
  users = User.collection.aggregate([
    { "$lookup": { from: "follows", localField: "_id", foreignField: "user_id", as: "follow" } },
    { "$unwind": "$follow" },
    { "$match": { "follow.followable_type": "User","follow.followable_id": BSON::ObjectId.from_string(userid) } },
    { "$group":{ _id: "$_id", data:{"$addToSet": "$$ROOT"}} },
    { "$unwind": "$data" },
    { "$project": {
        _id: 1,data: 1,count: 1,
        follow: {
          '$cond': {
            "if": { '$in': [ "$_id", f.first['data'] ]  }, "then": true,
            "else": false
          }
        }
      }
    },
    { "$skip": page * 10 },
    { "$limit": 10 }
  ])

The output:

name: Fausto Torres; Do I follow too? false; Counter that's make the magic: 1
name: kah; Do I follow too? false; Counter that's make the magic: 1
name: Marianno; Do I follow too? true; Counter that's make the magic: 2
name: Diego_Lukmiller; Do I follow too? true; Counter that's make the magic: 2

The query performs pretty fast and looks simple. Is there way / How do I solve it in a single query?!?

fct
  • 311
  • 3
  • 18