IndexOf in arrays of objects in Node

I am not sure on the use of indexOf in arrays of objects

The code which is not working is:

if (res.locals.company.companies.indexOf(req.query.companyId) >= 0) return next()

The if condition will always return false.

I also tested in console and it is actually wrong:

>> var zio = { __v: 1,
  _id: '50bc0238049a1ff10b000001',
  companies: 
   [ { _id: '50bc01938f164ee80b000001', name: 'Test' },
     { _id: '50bc01ac4e860ee90b000001', name: 'zio' } ],
}

>> zio.companies.indexOf("50bc01938f164ee80b000001")
-1

whereas it should be true.

Should I use any mysterious underscore utility ?

UPDATE/Clarification: my aim is just to check if 50bc01938f164ee80b000001 exists in one of the ids, I don't need to know where it actually is. This is very performance critical!

Nodejs solutions or tips would be amazing!

It's not wrong. That Array does not contain a String like that, but only two Object references. Hence, the result is correctly -1.

To get the index from the Object reference containing the searched string value, we could go like

var index;
zio.companies.some(function( obj, idx ) {
    if( obj._id === '50bc01938f164ee80b000001' ) {
        index = idx;
        return true;
    }
});

console.log('index is: ', index);

Based on your ninja edit, if you just want to know whether or not an object ref holding a specific id is contained by that array, use it like

var check = zio.companies.filter(function( obj ) {
    return obj._id === '50bc01938f164ee80b000001';
});

if( check.length ) {
    console.log('yep');
} else {
    console.log('nope');
}

Second edit: If you are really and only after performance, you probably don't want to have any function call overhead in any search. I'd use something like

function inObject(arr, search) {
    var len = arr.length;
    while( len-- ) {
        if(arr[len]._id === search)
           return true;
    }
}

if( inObject( zio.companies, 'AAA' ) ) {
}

That code outclasses any snippet provided here by a few magnitudes. See Here

You'll need to loop over the elements and check for the _id being equal.

indexOf checks for strict equality, and those objects are of course not equal to that string. (It's the same logic as "hello" === {foo: "hello"}. That will always be false.)

I'm sure with node there's some fancy way to do that, but the bare-JS way is:

var i,
    arr = [{foo: 'bar'}, {foo: 'baz'}],
    idx = -1;
for (i = 0; i < arr.length; ++i) {
    if (arr[i].foo === 'bar') {
        idx = i;
        break;
    }
}

You could also easily turn that into a function:

function indexOf(arr, pred) {
    for (var i = 0; i < arr.length; ++i) {
        if (pred(arr)) {
            return i;
        }
    }
    return -1;
}

That would give you a lot more verbose usage though (and a bit worse performance), but it might also be a bit more flexible if you find yourself needing to do it often.

console.log(indexOf(arr, function(elem) { return elem.foo === 'bar'; });

Your companies seems to be an array of objects (not ids), which has Id as one of the attributes. indexOf function is used to find the index of the matching element. Since you are passing an ID value to search the index, its not finding it as an element on the array hence returning false.

To fix the problem, you have two options:

  1. Iterate the companies element compare the ID value, if matched return true otherwise false.

  2. Use the object with desired id in as argument in the indexOf function. If value is greater than -1, return true otherwise false.

.indexOf is returning the correct output; your array doesn't have an element with that string. In fact, it's an array holding two object literals. You don't need .indexOf for objects, instead we must make our own function:

 var inObject = function( object, val ) {

     for (var i in object) { if ( object.hasOwnProperty(i) ) {

             if ( obj[i] === val ) {

                 return true;
             }

         }

     }
     return false;
 };

>>> inObject( zio.companies[0], '50bc01938f164ee80b000001' );
    : true