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.

3 Answers 3

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

Sign up to request clarification or add additional context in comments.

5 Comments

In case you need to check recursively you can look at this question here stackoverflow.com/questions/2631001/…
@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.
I used getProp in the end, very handy. Thanks.
Actually, it's not working for me - it seems to return an empty object in the case that it is not defined.
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: jsfiddle.net/11xrrxo1
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.

2 Comments

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: 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...
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 } 

2 Comments

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.
You are right, i assumed the type from the example code. techfoobar's answer is more correct.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.