var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope) {
  $scope.name = 'World';
  $scope.users = [
    {
      id: 1,
      name: 'John Doe',
      ranks: [ 
        { id: 1, name: 'Admin',subRanks: [{id: 34},{id: 45}]},
        { id: 2, name: 'Doe' }
        ],
    },
    {
      id: 1,
      name: 'Barbara Doe',
      ranks: [ { id: 15, name: 'Wife' , subRanks: [{id: 34},{id: 50}]}, { id: 2, name: 'Doe' }],
    },
  ];
});

app.filter('objectByKeyValFilter', function () {
    return function (input, filterKey, filterVal) {

        var filteredInput = [];

        var ContainsKeyValue = function (obj, key, value) {
            if (obj[key] === value) return true;
            for (var all in obj) {
                if (obj[all] != null && obj[all][key] === value) {
                    return true;
                }
                if (typeof obj[all] == "object" && obj[all] != null) {
                    var found = ContainsKeyValue(obj[all], key, value);
                    if (found == true) return true;
                }
            }
            return false;
        };

        for (var items in input) {
            if (ContainsKeyValue(input[items], filterKey, filterVal) === true) {
                filteredInput.push(input[items]);
            }
        }
        return filteredInput;
    }
});

// Strict filter for comparing objects like "give me all users having rank with id 1":
// {{ user in users | strictFilter:{ranks: [{id: 1}]} }}
// Standart filter will return also users having ranks with id 10, 12 or 100500
app.filter('strictRecurrentFilter', function($filter) {
  var strictComparator; // Very strict comparator to get very strict results
  strictComparator = function(actual, expected) {
    var objKey;
    if (actual && expected && actual instanceof Array && expected instanceof Array) {
      for (var arrIdx in actual) {
        if (strictComparator(actual[arrIdx], expected[0])) return true;  
      }
    } else if (actual && expected && typeof actual === "object" && typeof expected === "object") {
      for (objKey in actual) {
        if (objKey.charAt(0) !== "$" && hasOwnProperty.call(actual, objKey) && strictComparator(actual[objKey], expected[objKey])) {
          return true;
        }
      }
      return false;
    }
    return angular.equals(actual, expected);
  };
  // Use standard filter with our strict comparator
  return function(array, expression) {
    return $filter('filter')(array, expression, strictComparator);
  };
});
<!DOCTYPE html>
<html ng-app="plunker">

  <head>
    <meta charset="utf-8" />
    <title>AngularJS Plunker</title>
    <script>document.write('<base href="' + document.location + '" />');</script>
    <link rel="stylesheet" href="style.css" />
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.6/angular.min.js"></script>
    <script src="app.js"></script>
  </head>

  <body ng-controller="MainCtrl">
    <p>Hello {{name}}!</p>
        <p>Try to enter 1, 2, and 15 into this field: <input ng-model="rank_id"></p>
    <p>Here is the users with rank id beginning with {{rank_id}} (standard filter)</p>
    <ul>
      <li ng-repeat="user in users | filter:{ranks: {id: rank_id}}">
        {{ user }}
      </li>
    </ul>
    <p>Here is the users with rank id {{rank_id}} (strict filter — see angular js filter for more)</p>
    <ul>
      <li ng-repeat="user in users | filter:{ranks: {id: 1}} : true"> 
        {{ user }}
      </li>
    </ul>
    <p>Here is the users with sub rank id (strict recurrent filter — see file app.js)</p>
    <ul>
      <li ng-repeat="user in users | strictRecurrentFilter:{ranks: {subRanks: {id: 1 * rank_id } }}">
        {{ user }}
      </li>
    </ul>
    <p>And all users as is</p>
    <ul>
      <li ng-repeat="user in users">
        {{ user }}
      </li>
    </ul>
  </body>

</html>