0

I am trying to filter embedded documents by String (LIKE Query SQL equivalent) from the parent document.

Here's what I have now:

def resolve_friend(root, info, **kwargs):
    phone = kwargs.get('phone', None)
    search_string = kwargs.get('searchString', None)
    try:
        // I am retrieving the parent doucment by phone number first
        account = AccountModel.objects(phone=phone).first()

        if account is None:
            return ResponseMessageField(is_success=False, message="User does not exists.")

        top_friends = None

        // Now I want to filter the Friends field from the account by the search string.
        // In the friends' field, there are multiple documents.  The idea is to get the friends
        // matching the string from their first_name / last_name 

        if search_string:
            regex = re.compile('.*' + search_string + '.*', re.IGNORECASE)

            //doesn't work any of these below
            # top_friends = account.friends.filter((Q(first_name='test') | Q(last_name='test'))) 
            top_friends = AccountModel.objects(friends__first_name__icontains='tes').all() 


        all_friends = account.friends.filter(request_status="ACCEPTED")   //this works fine
        return retrieve_friend_list_graphql(top_friends=top_friends, all_friends=all_friends)
    except Exception as e:
        return ResponseMessageField(is_success=False, message="Account fetch error. " + str(e))

These lines don't work

top_friends = account.friends.filter((Q(first_name='test') | Q(last_name='test'))) 
top_friends = AccountModel.objects(friends__first_name__icontains='tes').all() 

I am unable to filter the account.friends.filter() with the search string in mongoengine.

Here's the full account document with the friends field.

{
  "_id": {
    "$oid": "5e3485c2dd26ea191faf2861"
  },
  "identity": "0b1170fc50979464c352c34c2e9fd7aa",
  "username": "Shuvro",
  "first_name": "",
  "middle_name": "",
  "last_name": "",
  "phone": "+8801521483999",
  "is_active": false,
  "is_activation_sent": true,
  "activation_code": "9815",
  "is_phone_confirmed": false,
  "is_email_active": false,
  "is_email_activation_sent": true,
  "email_activation_code": "7529c11c2b0eb55314fb01355d5cc78f",
  "is_email_confirmed": false,
  "friends": [
    {
      "identity": "bb30337b7fbcc5080b9fe3a2b6a60383",
      "username": "Shuvro",
      "first_name": "lord",
      "middle_name": "",
      "last_name": "",
      "email": "shuvro@test.com",
      "phone": "+8801521483720",
      "request_status": "PENDING",
      "request_type": "RECEIVED",
      "request_created_at": {
        "$date": {
          "$numberLong": "1580676652938"
        }
      }
    },
    {
      "identity": "06df8a2dd85c3ebc5b49817333f2aeff",
      "username": "",
      "first_name": "test",
      "middle_name": "",
      "last_name": "test last",
      "phone": "+8801521474747",
      "request_status": "PENDING",
      "request_type": "RECEIVED",
      "request_created_at": {
        "$date": {
          "$numberLong": "1581876704806"
        }
      }
    }
  ]
}

Please help, how can I filter out the friends by their name from the parent document. Thanks.

solarissmoke
  • 30,039
  • 14
  • 71
  • 73
Nazmul
  • 500
  • 6
  • 17

1 Answers1

0

You can try using a __raw__ query using the mongodb regex operator, for example:

AccountModel.objects(__raw__={"friends": { "$elemMatch": { "first_name": { "$regex": ".*test.*" } } } })

Obviously, if you want to limit the results to only one user, you shall pass the account id together.

AccountModel.objects(__raw__={"friends": { "$elemMatch": { "first_name": { "$regex": ".*test.*" } } }, "_id" : account.id })

Hope it suits you well.

Kenny Aires
  • 1,338
  • 12
  • 16
  • Thanks for the reply @Kenny. But that doesn't work. As I already have the document in `account`, I need to filter results on the `Friends` field only. – Nazmul Feb 17 '20 at 21:52
  • @Shuvro my bad... now I see it's an embeded document, I've updated my answer, check if it works now please. Just tested here on my code a similar context. – Kenny Aires Feb 17 '20 at 22:02
  • that's returning the parent document itself. but I need to get the matching embedded document. – Nazmul Feb 17 '20 at 22:09
  • @Shuvro I see what you mean now... it's a hard query, the following answer might give you some light: https://stackoverflow.com/a/15680567/8969084 – Kenny Aires Feb 17 '20 at 23:22