1

The below script outputs

================================================
Log entry ID: 1
UUID: 2
Timestamp: 3
--------------------
Log entry ID: 4
UUID: 5
Timestamp: 6

which is what I want.

Right now description is hard coded, where I would like it to be built using arr instead.

My current thinking were to somehow generate the inner array in the map() function:

[
    `Log entry ID: ${element['_id']}`,
    `UUID: ${element['_source'].uuid}`,
    `Timestamp: ${element['_source']['@timestamp']}\n`,
]

but because of the templating, this is not even a valid array with 3 elements, when looking at it on its own. So I am all out of ideas.

Question

Somehow I have to loop over the elements in arr before it is given to map(), I suppose.

Does anyone know how that could be done?

const dedent = require('dedent');

const arr = [
  [ 'Log entry ID', '_id' ],
  [ 'UUID', 'uuid' ],
  [ 'Timestamp', '@timestamp' ],
]
;

const docs = [
  {'_id': 1,'_source': {'uuid': 2,'@timestamp': 3}},
  {'_id': 4,'_source': {'uuid': 5,'@timestamp': 6}},
];

const description = dedent`
================================================
${
  docs.map((element) => [
    `Log entry ID: ${element['_id']}`,
    `UUID: ${element['_source'].uuid}`,
    `Timestamp: ${element['_source']['@timestamp']}\n`,
  ].join('\n')).join('--------------------\n')
}
`;

console.log(description);

Update

I control arr so changing it to eg. is possible, or something else

const arr = [
  [ 'Log entry ID', '_id' ],
  [ 'UUID', {'_source': 'uuid'} ],
  [ 'Timestamp', {'_source': '@timestamp'} ],
]
;
Sandra Schlichting
  • 25,050
  • 33
  • 110
  • 162
  • 1
    It's a little bit confusing that the keys you want to access have different depths (_id: 1, uuid:2, etc). Do you control both vars: `arr` and `docs`? – Johan Dettmar Nov 03 '21 at 08:45
  • @JohanDettmar I control `arr`, so it could be structured differently if that makes it easier. – Sandra Schlichting Nov 03 '21 at 08:48
  • 1
    If you know that the keys will be unique for the entire item of `docs`, regardless of depth, it's sufficient to do a search solely on that key name. Otherwise we would need a unique "key path" to the value of interest. – Johan Dettmar Nov 03 '21 at 08:53
  • @JohanDettmar What if `_source` somehow could be included in the elements of `arr`, so there won't be a need for a search? – Sandra Schlichting Nov 03 '21 at 08:58
  • @JohanDettmar I have now updated OP, where I have suggested another way to structure `arr` so hopefully no searching is needed? – Sandra Schlichting Nov 03 '21 at 09:03

3 Answers3

2

Since arr is in your control perhaps you can specify the path of the key itself.

const arr = [
  ['Log entry ID', '_id'],
  ['UUID', '_source.uuid'],
  ['Timestamp', '_source.@timestamp'],
  ['Description', '_source._desc']
];

const docs = [{
    '_id': 1,
    '_source': {
      'uuid': 2,
      '@timestamp': 3,
      '_desc': 'test 1'
    }
  },
  {
    '_id': 4,
    '_source': {
      'uuid': 5,
      '@timestamp': 6,
      '_desc': 'test 2'
    }
  },
];

const getValue = (object, keys) => keys.split('.').reduce((o, k) => (o || {})[k], object);

console.log(docs.map((element) => arr.map((label) => {
  return `${label[0]}: ${getValue(element, label[1])}`
}).join('\n')).join('\n--------------------\n'))
abhishek khandait
  • 1,990
  • 2
  • 15
  • 18
  • Can you explain what `getValue()` does? I have never used `reduce()` before so I can't quite figure out what problem `getValue()` solves? – Sandra Schlichting Nov 03 '21 at 10:56
  • `getValue` method converts a javascript string in dot notation into an object reference. Basically `_source.uuid` is the key to get uuid from docs, so getValue will iterate into docs object to search `_source.uuid`. – abhishek khandait Nov 11 '21 at 08:14
1

Assuming that the keys of a docs array element are all unique, one could traverse the object looking for a matching key.

function findVal(object, key) {
    var value;
    Object.keys(object).some(function(k) {
        if (k === key) {
            value = object[k];
            return true;
        }
        if (object[k] && typeof object[k] === 'object') {
            value = findVal(object[k], key);
            return value !== undefined;
        }
    });
    return value;
}


docs.map((element) =>
arr.map(([item, key]) =>
    `${item}: ${findVal(element, key)}`)
)

The FindVal is taken from here.

Johan Dettmar
  • 27,968
  • 5
  • 31
  • 28
0

you could create a function to get data from arr and put in description

/* Simple Hello World in Node.js */

const arr = [
  [ 'Log entry ID', '_id' ],
  [ 'UUID', 'uuid' ],
  [ 'Timestamp', '@timestamp' ],
]
;

const docs = [
  {'_id': 1,'_source': {'uuid': 2,'@timestamp': 3}},
  {'_id': 4,'_source': {'uuid': 5,'@timestamp': 6}},
];
const findInArr=function(value){
    var t = ""
    arr.forEach(item=>{
        if (item.includes(value)) {t = item[0]}
        
    })
    return t
}
const description = dedent`
================================================
 ${
 docs.map((element) => [
    `${findInArr('_id')}: ${element['_id']}`,
    `${findInArr('UUID')}: ${element['_source'].uuid}`,
    `${findInArr('Timestamp')}: ${element['_source']['@timestamp']}\n`,
  ].join('\n')).join('--------------------\n')
}`;

console.log(description);
mohammad Naimi
  • 2,259
  • 1
  • 5
  • 15