Convert nested array of object to object of object in js - nested

This is my code, and I tried to convert all nested array of object to objects of object and want to add subParentData value as key of the object if key is present
```let flow = [{
"children": {
"_": [{
"data": {},
"children": {
"_": [{
"data": {},
"children": {
"_": [{
"data": {},
"children": {
"_": []
},
"module": "C"
}]
},
"module": "conference",
"subParentData": "6"
},
{
"data": {},
"children": {
"_": [{
"data": {},
"children": {
"_": []
},
"module": "D"
}]
},
"module": "play",
"subParentData": "6"
}
]
},
"module": "B"
}]
},
"module": "A"
}];```
I want to convert my json like this, If you see all array of object after '_' key replaced with the objects and if subParentData value is present then the value of subParentData added as key of that object..
let flow = [{
"children": {
"_": {
"data": {},
"children": {
"6": {
"data": {},
"children": {
"_": {
"data": {},
"children": {
"_": {}
},
"module": "C"
}
},
"module": "conference",
"subParentData": "6"
},
"5": {
"data": {},
"children": {
"_": {
"data": {},
"children": {
"_": {}
},
"module": "D"
}
},
"module": "play",
"subParentData": "5"
}
},
"module": "B"
}
},
"module": "A"
}];```
My update json will look like this..

Related

Return the documents if the array field length greater than 0 in esclient nodejs

I have millions of documents in my es index.
I wanted to fetch the documents where the array field length greater than 0.
My docs looks like this
[
{
"primaryKey": "9c30d9e8-af04-4cc8-afcb-0c1311988c1e",
"language": "all",
"industry": [
"Accounting & auditing"
],
"text": "what's the status of my incident?",
"textId": "d0c70fc4-5e2a-4cab-a5f6-32339e6632dd",
"extractions": [],
"active": true,
"status": "active",
"createdAt": 1620208485092,
"updatedAt": 1620208485092,
"secondaryKey": "5db5f725-ec09-49da-9507-7bb2f94fd741"
},
{
"primaryKey": "9c30d9e8-af04-4cc8-afcb-0c1311988c1e",
"language": "all",
"industry": [
"Accounting"
],
"text": "What is the rating of my incident",
"textId": "4a53533f-293e-440c-aaa9-f7e5ae1436ca",
"extractions": [
{
"name": "Abinas Patra",
"role": "api-user",
"primaryKey": "ed12851d-c18d-4c92-8cc3-1782e41bc9d0"
},
{
"name": "Anil Patra",
"role": "ui-user",
"primaryKey": "933fad33-78b3-4779-a7bd-c62c6e02af75"
}
],
"active": true,
"status": "active",
"createdAt": 1620208485092,
"updatedAt": 1620208485092,
"secondaryKey": "5db5f725-ec09-49da-9507-7bb2f94fd741"
}
]
I am using elasticsearch nodejs client.
I tried in the below way
let dataCount = await esClient.count({
index: "indexName",
type: "docType",
body: {
query: {
bool: {
must: [
{
"script": {
"script": {
"inline": "doc['extractions'].values.length > 0",
"lang": "painless"
}
}
},
{
"match": {
"primaryKey": {
query: primaryKey,
"operator": "and"
}
}
},
{
"match": {
"language": {
query: language,
"operator": "and"
}
}
}
]
}
}
}
});
I get runtime parsing error everytime, i tried with exist field as well.
{"error":{"root_cause":[{"type":"script_exception","reason":"runtime error","script_stack":["org.elasticsearch.search.lookup.LeafDocLookup.get(LeafDocLookup.java:65)","org.elasticsearch.search.lookup.LeafDocLookup.get(LeafDocLookup.java:27)","doc[\'extractions\'].values.length > 1"," ^---- HERE"],
tried this as well
must_not:[
{
"script": {
"script": "_source.extractions.size() > 0"
}
}
]
Can anyone please help here.
thanks :)

Filtering In mongoose aggregation

I have a listing object with filters. I need to create an aggregation to filter the listings based on filters.
This is a listing object example
[
{
"_id": "5c484ec4cb1e150b1efce101",
"details": {
"title": "Villa 1",
"description": "Description about Villa 1"
},
"options": {
"features": [
"5c482b1ff9f18807694040c6",
"5c482b2ef9f18807694040c7",
"5c482b3af9f18807694040c8",
"5c482b49f9f18807694040c9"
],
"filters": [
{
"filter": "5c482c2c2abe2f07ccd5d428",
"value": 7
},
{
"filter": "5c482c392abe2f07ccd5d429",
"value": 3
},
{
"filter": "5c482c462abe2f07ccd5d42a",
"value": 5
},
{
"filter": "5c482c4d2abe2f07ccd5d42b",
"value": 2
},
{
"filter": "5c482c562abe2f07ccd5d42c",
"value": true
},
{
"filter": "5c482c612abe2f07ccd5d42d",
"value": true
}
]
},
"memberOnly": false,
"feature": false,
"active": true,
"Category": "5c45af3b5ccf2c20833a547a"
},
{
"_id": "5c484ec4cb1e150b1efce101",
"details": {
"title": "Villa 2",
"description": "Description about Villa 2"
},
"options": {
"features": [
"5c482b1ff9f18807694040c6",
"5c482b2ef9f18807694040c7",
"5c482b3af9f18807694040c8",
"5c482b49f9f18807694040c9"
],
"filters": [
{
"filter": "5c482c2c2abe2f07ccd5d428",
"value": 5
},
{
"filter": "5c482c392abe2f07ccd5d429",
"value": 7
},
{
"filter": "5c482c462abe2f07ccd5d42a",
"value": 2
},
{
"filter": "5c482c4d2abe2f07ccd5d42b",
"value": 6
},
{
"filter": "5c482c562abe2f07ccd5d42c",
"value": true
},
{
"filter": "5c482c612abe2f07ccd5d42d",
"value": true
}
]
},
"memberOnly": false,
"feature": false,
"active": true,
"Category": "5c45af3b5ccf2c20833a547a"
}
]
I need a mongoose aggregation to be able to filter between objects based on the filter and its value
example:
i need to filter listings that have
filter "5c482c2c2abe2f07ccd5d428" with a value $gte:4
filter "5c482c4d2abe2f07ccd5d42b" with a value $gte:3
filter "5c482c612abe2f07ccd5d42d" with a true value
When I filter the expected result should be
[
{
"_id": "5c484ec4cb1e150b1efce101",
"details": {
"title": "Villa 1",
"description": "Description about Villa 1"
},
"options": {
"features": [
"5c482b1ff9f18807694040c6",
"5c482b2ef9f18807694040c7",
"5c482b3af9f18807694040c8",
"5c482b49f9f18807694040c9"
],
"filters": [
{
"filter": "5c482c2c2abe2f07ccd5d428",
"value": 7
},
{
"filter": "5c482c392abe2f07ccd5d429",
"value": 3
},
{
"filter": "5c482c462abe2f07ccd5d42a",
"value": 5
},
{
"filter": "5c482c4d2abe2f07ccd5d42b",
"value": 2
},
{
"filter": "5c482c562abe2f07ccd5d42c",
"value": true
},
{
"filter": "5c482c612abe2f07ccd5d42d",
"value": true
}
]
},
"memberOnly": false,
"feature": false,
"active": true,
"Category": "5c45af3b5ccf2c20833a547a"
}
]
the solution was
Listing.find({
$and: [{
'options.filters': {
$elemMatch: {
filter: this.mongoose.Types.ObjectId('5c482c2c2abe2f07ccd5d428'),
value: {$gte: 4}
}
}
}, {
'options.filters': {
$elemMatch: {
filter: this.mongoose.Types.ObjectId('5c482c4d2abe2f07ccd5d42b'),
value: {$gte: 3}
}
}
}, {
'options.filters': {
$elemMatch: {
filter: this.mongoose.Types.ObjectId('5c482c612abe2f07ccd5d42d'),
value: true
}
}
});

Get nested value in array based on condition for another value in that array

I had difficulty creating a title for this question…
Say I have data like this:
{"total_results":78,"resources":[{"metadata":{"verified_at":"2018-10-17T21:07:43.935Z","linkages":[{"origin":"ABC","id":"a"},{"origin":"XYZ","id":"b"}]}},{"metadata":{"verified_at":"2018-10-17T21:07:43.935Z","linkages":[{"origin":"ABC","id":"c"},{"origin":"XYZ","id":"d"}]}}]}
Consider the resources field. I want to output an array that includes an id for each array element. To get the ID, go to the linkages field, which is an array, and find the element that has "origin": "ABC". The id field in that element is the ID that should be returned.
This code snippet works, but it seems too verbose. There must be an easier way.
_.map(_.filter(_.flatten(_.map(body.resources, 'metadata.linkages')),['origin','ABC']), 'id')
You could do something like this:
var data = { "total_results": 78, "resources": [ { "metadata": { "verified_at": "2018-10-17T21:07:43.935Z", "linkages": [{ "origin": "ABC", "id": "a" }, { "origin": "XYZ", "id": "b" }] } }, { "metadata": { "verified_at": "2018-10-17T21:07:43.935Z", "linkages": [{ "origin": "ABC", "id": "c" }, { "origin": "XYZ", "id": "d" }] } } ] }
const result = _(data.resources)
.flatMap('metadata.linkages')
.filter(['origin', 'ABC'])
.map('id')
.value()
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>
With chaining and flatMap + filter & map
Another approach would be with flatMap & reduce:
var data = { "total_results": 78, "resources": [ { "metadata": { "verified_at": "2018-10-17T21:07:43.935Z", "linkages": [{ "origin": "ABC", "id": "a" }, { "origin": "XYZ", "id": "b" }] } }, { "metadata": { "verified_at": "2018-10-17T21:07:43.935Z", "linkages": [{ "origin": "ABC", "id": "c" }, { "origin": "XYZ", "id": "d" }] } } ] }
const result = _(data.resources)
.flatMap('metadata.linkages')
.reduce((r,c) => (_.isEqual(c.origin, 'ABC') ? r.push(c.id) : null, r), [])
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>
Another more concise version:
var data = { "total_results": 78, "resources": [{ "metadata": { "verified_at": "2018-10-17T21:07:43.935Z", "linkages": [{ "origin": "ABC", "id": "a" }, { "origin": "XYZ", "id": "b" }] } }, { "metadata": { "verified_at": "2018-10-17T21:07:43.935Z", "linkages": [{ "origin": "ABC", "id": "c" }, { "origin": "XYZ", "id": "d" }] } }] }
const result = _.reduce(data.resources, (r,c) =>
(r.push(_.find(c.metadata.linkages, {origin: 'ABC'}).id), r), [])
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>
With ES6 you can go with something like this:
var data = { "total_results": 78, "resources": [{ "metadata": { "verified_at": "2018-10-17T21:07:43.935Z", "linkages": [{ "origin": "ABC", "id": "a" }, { "origin": "XYZ", "id": "b" }] } }, { "metadata": { "verified_at": "2018-10-17T21:07:43.935Z", "linkages": [{ "origin": "ABC", "id": "c" }, { "origin": "XYZ", "id": "d" }] } }] }
const result = data.resources.reduce((r,c) =>
(r.push(c.metadata.linkages.find(x => x.origin == 'ABC').id), r), [])
console.log(result)

Mongoose find document by key whose value is a complex object

I am using Mongoose to do a search for documents in a collection based on the criteria described below:
Document:
{
"_id": {
"$oid": "5a60621e20205641281f7c2f"
},
"key1": [
{
"available": true,
"required": true,
"name": "Name-1"
},
{
"available": true,
"required": true,
"name": "Name-2"
},
{
"available": true,
"required": true,
"name": "Name-3"
}
],
"__v": 0
}
I want to perform a search based on property key1. So basically what I want to do is pass the json object as search pattern below and get the result as the document above in return
[
{
"available": true,
"required": true,
"name": "Name-1"
},
{
"available": true,
"required": true,
"name": "Name-2"
},
{
"available": true,
"required": true,
"name": "Name-3"
}
]
Is there a way that I can achieve this?
You can check $eq in mongodb docs $eq.
const selector = [
{
"available": true,
"required": true,
"name": "Name-1"
},
{
"available": true,
"required": true,
"name": "Name-2"
},
{
"available": true,
"required": true,
"name": "Name-3"
}
];
Model.find({key1: {$eq: selector}}, (error, result) => {
if(!err) {
res.send(result);
}
});
Model is the collection you fetch from.

loopback model json array of objects strict filter

I'm using strongloop loopback v3 REST API with mongoDB as datasource. My model order.json is
{
"name": "order",
"base": "PersistedModel",
"strict": true,
"idInjection": true,
"options": {
"validateUpsert": true
},
"properties": {
"orderNo": {
"type": "string"
},
"lines": {
"type": [
{
"type": {
"description": "string",
"quantity": "number"
}
}
]
}
},
"validations": [],
"relations": {},
"acls": [],
"methods": {}
}
I set "strict": true so that the model accepts only predefined properties. But this does not work for properties in the array lines.
I.E. if you post this object to the API you get an ValidationError (Code 422) as expected:
{
"orderNo": "xyz",
"someOtherProp": "hello",
"lines": [
{
"description": "abc",
"quantity": 5
}
]
}
But if you post this JSON object loopback saves the object to mongoDB
{
"orderNo": "xyz",
"lines": [
{
"description": "abc",
"quantity": 5,
"someOtherProp": "hello"
}
]
}
My question is about if there are any flags to be set in the model JSON to validate an array of objects? Or do I have to validate the nested documents by my own via the order.js model extension file?
define the lines as another model and make it relation with type embedsMany in order model.
lines model
{
"name": "line",
"base": "Model",
"strict": true,
"idInjection": true,
"properties": {
"description": {
"type": "string"
},
"quantity":{
"type":"number"
}
}
}
order model
{
"name": "order",
"base": "PersistedModel",
"strict": true,
"idInjection": true,
"options": {
"validateUpsert": true
},
"properties": {
"orderNo": {
"type": "string"
}
},
"validations": [],
"relations": {
"lines":{
"type": "embedsMany",
"model": "line",
"property": "lines"
}
},
"acls": [],
"methods": {}
}
this way loopback will validate line model

Resources