0

I have a object defined as

{
    "query" :
    {
        /* snip */
    },
    "aggs":
    {
        "times" :
        {
            "date_histogram" :
            {
                "field" : "@timestamp",
                "interval" : "15m",
                "format" : "HH:mm",
                "min_doc_count" : 0
            }
        }
    }
};

How can I tell whether interval in aggs.times.date_histogram exists, so that I can manipulate it?

Clarification: I can not be sure that any of the parent objects to interval exist.

pjcard
  • 1,088
  • 10
  • 22

3 Answers3

3

You can check it with typeof:

if(typeof aggs.times.date_histogram['interval'] !== 'undefined') {
    // ... exists ...
}

Another method is using the in keyword (this one is prettier and more obvious imho)

if('interval' in aggs.times.date_histogram) {
    // ... exists ...
}

The above is assuming aggs.times.date_histogram exists (and doesn't need an existence check)


Update: For checking the existence of everything leading to the value you need, you can use this:

function getProp(_path, _parent) {
   _path.split('.').forEach(function(_x) {
       _parent = (!_parent || typeof _parent !== 'object' || !(_x in _parent)) ? undefined : _parent[_x];
   });
   return _parent;
}

You can call it like:

getProp('aggs.times.date_histogram.interval', parent_of_aggs);

Will return the value of interval if it is defined, else it will return undefined

techfoobar
  • 65,616
  • 14
  • 114
  • 135
  • 1
    In case you need to check recursively you can look at this question here http://stackoverflow.com/questions/2631001/javascript-test-for-existence-of-nested-object-key – Treesrule14 Jun 04 '15 at 13:45
  • @Treesrule14 Yours was the answer I am looking for - I'm surprised that from that answer there's no good way to do it. I'll update my question to make it clear that the intervening objects may be absent. – pjcard Jun 04 '15 at 14:01
  • I used getProp in the end, very handy. Thanks. – pjcard Jun 05 '15 at 08:05
  • Actually, it's not working for me - it seems to return an empty object in the case that it is not defined. – pjcard Jun 05 '15 at 14:07
  • Oh, i see. Perhaps its something to do with what you are passing as the second argument. Been using `getProp()` for a couple years without any issues so far. Example: https://jsfiddle.net/11xrrxo1/ – techfoobar Jun 06 '15 at 04:18
2

Assuming the value is always a non-blank string, just test it for truthiness:

if (aggs.times.date_histogram.interval) {
    // Use it
}

You might cache the result of those property lookups. Though it's unlikely to really matter for performance, it may be useful for code maintainability:

var interval = aggs.times.date_histogram.interval;
if (interval) {
    // Use it
}

If you need to worry that each level may not exist, it gets more verbose:

if (aggs &&
    aggs.times &&
    aggs.times.date_histogram &&
    aggs.times.date_histogram.interval) {
    // Use it
}

There's a question with several answers about writing a function for that.

Community
  • 1
  • 1
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • You guessed the nature of my inexact question, I do need to worry about each level. I'll update my question accordingly. Thank you. – pjcard Jun 04 '15 at 14:02
  • 1
    @pjcard: No worries. You said in another comment you were surprised there wasn't a shorter way. A few years ago on the es5-discuss mailing list there was talk of a short-circuiting property accessor operator which would let you do that. I forget what the operator was, but say it was `..`, then you'd do: `aggs..times..date_histogram..interval` and you'd get `undefined`, rather than an error, if any level didn't exist. IIRC, it didn't meet the "pulls its syntactic weight" requirement and wasn't advanced. :-| Too bad, in my view, but... – T.J. Crowder Jun 04 '15 at 14:22
0
test = {
"query" :
{
    /* snip */
},
"aggs":
{
    "times" :
    {
        "date_histogram" :
        {
            "field" : "@timestamp",
            "interval" : "15m",
            "format" : "HH:mm",
            "min_doc_count" : 0
        }
    }
}
};

Use this:

if(test.aggs.times.date_histogram.interval) {
    alert('true'); //your code here
} else {
    alert('false'); //your code here
}
Preda Bogdan
  • 106
  • 2
  • 7
  • 1
    This will usually work but has the same caveat as T.J. in that the value must be assumed to always be "truthy". If the value of 'interval' was "falsey" (ex: false) for some reason, it would behave as if there was no property defined. – AnthonyDJ Jun 04 '15 at 13:53
  • 1
    You are right, i assumed the type from the example code. techfoobar's answer is more correct. – Preda Bogdan Jun 04 '15 at 13:57