This is the structure which is saved in the database. I want to fetch only "entityInfo" directly without using any loop.
let x = {
"12": [{
"entity": {
"id": "40ea18e6-f898-414a-96fd-b3ef5a0eb7cd"
},
"startTime": "2018-12-19T06:29:59.999Z"
},
{
"entity": {
"id": "40ea18e6-f898-414a-96fd-b3ef5a0eb7cd"
},
"startTime": "2018-12-19T06:49:25.000Z",
},
{
"entityInfo": [{
"entityName": "acd",
"timeSpent": 0.028055555555555556
}]
}
]
}
If you want the first item in the 12 array which has an entityInfo value, then you can use find
let x = {
"12": [{
"entity": {
"id": "40ea18e6-f898-414a-96fd-b3ef5a0eb7cd"
},
"startTime": "2018-12-19T06:29:59.999Z"
},
{
"entity": {
"id": "40ea18e6-f898-414a-96fd-b3ef5a0eb7cd"
},
"startTime": "2018-12-19T06:49:25.000Z",
},
{
"entityInfo": [{
"entityName": "acd",
"timeSpent": 0.028055555555555556
}]
}
]
}
console.log(x["12"].find(a => a.entityInfo))
You can use the map() function encapsulated. Click here.
But you have to question yourself if an array makes sense here.
let x = {
"12": [{
"entity": {
"id": "40ea18e6-f898-414a-96fd-b3ef5a0eb7cd"
},
"startTime": "2018-12-19T06:29:59.999Z"
},
{
"entity": {
"id": "40ea18e6-f898-414a-96fd-b3ef5a0eb7cd"
},
"startTime": "2018-12-19T06:49:25.000Z",
},
{
"entityInfo": [{
"entityName": "acd",
"timeSpent": 0.028055555555555556
}]
}
]
}
// will return a value if the entityInfo object exists
var ans = x["12"].filter((val)=>{return val.entityInfo})[0]
console.log(ans)
If there only is one entityInfo you can use the following to get the first element that has a "entityInfo" property.
x["12"].find(i => i.entityInfo)
Use Object.values for getting the values and then find for finding all the entity info objects
var x = {
"12": [{
"entity": {
"id": "40ea18e6-f898-414a-96fd-b3ef5a0eb7cd"
},
"startTime": "2018-12-19T06:29:59.999Z"
},
{
"entity": {
"id": "40ea18e6-f898-414a-96fd-b3ef5a0eb7cd"
},
"startTime": "2018-12-19T06:49:25.000Z",
},
{
"entityInfo": [{
"entityName": "acd",
"timeSpent": 0.028055555555555556
}]
}
]
};
console.log(Object.values(x).flat().find(el => el.entityInfo));
There are multiple approaches and possible solutions to this question.
You can use map, filter, reduce, find , forEach.
But each of the loop over elements internally, the other approach is if you know the position of entityInfo in x["12"] and you want to safe read it. Then you can use utilities like these.
Related
I have the following collection in MongoDB
[
{
"acronym": "front",
"references": [
{
"date": "2020-03-04",
"value": "5.6"
},
{
"date": "2020-03-05",
"value": "6.3"
}
]
}
]
I want to use the function $addToSet in order to add new document into references. I know that it can be done with the following code:
db.collection.update({
"acronym": "front"
},
{
$addToSet: {
"references": {
"date": "2020-03-06",
"value": "6"
}
}
})
And it will add the new document to the array references, so the result is the following:
[
{
"acronym": "front",
"references": [
{
"date": "2020-03-04",
"value": "5.6"
},
{
"date": "2020-03-05",
"value": "6.3"
},
{
"date": "2020-03-06",
"value": "6"
}
]
}
]
QUESTION: What I want to obtain is that in the case of adding a date that is already in the array, the update will no be produced.
Here is the playground: https://mongoplayground.net/p/DPER2RuROEs
Thanks!
You can add another qualifier to the update to prevent duplicated dates
db.collection.update({
"acronym": "front",
"references.date": {
$ne: "2020-03-04"
}
},
{
$addToSet: {
"references": {
"date": "2020-03-04",
"value": "6"
}
}
})
I got the solution from here
I would like to convert objects in JavaScript, but I'm not really sure of the best way to do it. I don't often code in the language so I don't really know much of the fundamentals- this is the object I get back from an API call in a React project:
{
"api": {
"results": 380,
"fixtures": [
{
"fixture_id": 65,
"league_id": 2,
"league": {
"name": "Premier League",
"country": "England",
"logo": "https://media.api-sports.io/football/leagues/2.png",
"flag": "https://media.api-sports.io/flags/gb.svg"
},
"event_date": "2018-08-10T19:00:00+00:00",
"event_timestamp": 1533927600,
"firstHalfStart": 1533927600,
"secondHalfStart": 1533931200,
"round": "Regular Season - 1",
"status": "Match Finished",
"statusShort": "FT",
"elapsed": 90,
"venue": "Old Trafford (Manchester)",
"referee": null,
"homeTeam": {
"team_id": 33,
"team_name": "Manchester United",
"logo": "https://media.api-sports.io/football/teams/33.png"
},
"awayTeam": {
"team_id": 46,
"team_name": "Leicester",
"logo": "https://media.api-sports.io/football/teams/46.png"
},
"goalsHomeTeam": 2,
"goalsAwayTeam": 1,
"score": {
"halftime": "1-0",
"fulltime": "2-1",
"extratime": null,
"penalty": null
}
}
]
}
}
I would like to convert it to this array (the array holds multiple objects):
[
{
"homeTeam": {
"id": 33,
"name": "Manchester United",
"teamId": 33
},
"awayTeam": {
"id": 46,
"name": "Leicester",
"teamId": 46
},
"outcome": {
"goalsScoredByAwayTeam": 2,
"goalsScoredByHomeTeam": 1
},
"resulted": true,
"type": "LEAGUE"
}
]
The teamId and id actually need to lookup another object before the final output.
I'm not sure what the best way to do it is. This is my function so far, trying to make use of optional chaining:
function convertFixturesToArray() {
fixturesStore.getFixtures()?.api?.fixtures?.length ? fixtures.api.fixtures.map(fixture => (
//TRANSFORMATION GOES IN HERE
)) : null;
}
You seem on the right track. It should be something like this (written in a slightly more modern JS)
convertFixturesToArray = () => fixturesStore.getFixtures()?.api?.fixtures?.map?.(fixture => {
//Do whatever check you need here with the fixture object
return {
homeTeam: { ...fixture.homeTeam },
awayTeam: { ...fixture.awayTeam },
outcome: {
goalsScoredByAwayTeam: fixture.goalsAwayTeam,
goalsScoredByHomeTeam: fixture.goalsHomeTeam,
},
type: 'LEAGUE',
resulted: true,
},
}) ?? [];
It looks like you're trying to get certain key/value pairs from your api response. With a mix of map, reduce, and find, you can get the values you're looking for by defining them in an array (i.e. desiredProps).
Of course, adding the "outcome" field and your other hardcoded fields would require a bit more logic on top of this. Boris' answer addresses this problem. I've taken a more flexible approach.
let apiResult = {
"fixtures": [
{
"prop1": "a1",
"prop2": "a2",
"prop3": "a3"
},
{
"prop1": "b1",
"prop2": "b2",
"prop3": "b3"
}
]
}
let desiredProps = ["prop2", "prop3"]
let result = apiResult.fixtures.map(x => {
return Object.keys(x).reduce((acc, curr) => {
if (desiredProps.find(y => y === curr)) {
acc[curr] = x[curr]
}
return acc
}, {})
})
console.log(result)
im facing a small issue in filtering the data in dynamice nested json array. Can someone please help me to resolve my issue..
var data = {
"root": {
"children": [{
"name": "Concept Phase",
"order": [{
"startTime": "20150101000000",
"endTime": "20150125000000"
}]
},
{
"name": "Design Phase",
"order": [{
"startTime": "2015012500000",
"endTime": "20150311000000"
}]
},
{
"name": "Validation Phase",
"order": [{
"startTime": "2015031100000",
"endTime": "20150430000000"
}]
},
{
"name": "Production Preparation",
"order": [{
"startTime": "2015043000000",
"endTime": "20150612000000"
}]
}
]
}
}
Above json objects may increase dynamically. Now im trying to filter the JSON by passing multiple objects(name,startTime,endTime). Below is the code im trying..
var filterBy = {
name: ["Concept Phase"],
startTime:["20150101000000"],
endTime: ["20150125000000"]
};
var result = data.root.children.filter(function (o) {
return Object.keys(filterBy).every(function (k) {
return filterBy[k].some(function (f) {
return o[k] === f;
});
});
});
Above code will work if i pass only name. Because im filtering only upto children. How can i filter the properties that are available in order?
For the Above JSON i need to pass name,startTime, endTime. And the expected output should look like below..
data = {
"root": {
"children": [{
"name": "Concept Phase",
"order": [{
"startTime": "20150101000000",
"endTime": "20150125000000"
}]
}
]
}
}
Can someone please help me to resolve the issue?
Thank you in advance..
You can set exact object in filterBy variable as below
var filterBy = {
name: "Concept Phase",
order:[{
"startTime": "20150101000000",
"endTime": "20150125000000"
}]
};
and then use below code to filter objects from children array
var result = data.root.children.filter(function (o) {
return JSON.stringify(o) === JSON.stringify(filterBy)
});
You also use underscore js functions _.isEqual to compare objects which is useful if order of key value pairs is different in original object
You are using .every() and .some() in the wrong way, I would suggest you read more about them to understand how they are used. So the issue with your .every() function call is it return a function call instead of returning TRUE/FALSE value that's why its just in its just take the first element of filterBy object key array, to achieve what you want I would do it like:
var data = {
"root": {
"children": [{
"name": "Concept Phase",
"order": [{
"startTime": "20150101000000",
"endTime": "20150125000000"
}]
},
{
"name": "Design Phase",
"order": [{
"startTime": "2015012500000",
"endTime": "20150311000000"
}]
},
{
"name": "Validation Phase",
"order": [{
"startTime": "2015031100000",
"endTime": "20150430000000"
}]
},
{
"name": "Production Preparation",
"order": [{
"startTime": "2015043000000",
"endTime": "20150612000000"
}]
}
]
}
}
var filterBy = {
name: ["Concept Phase"],
startTime:["20150101000000"],
endTime: ["20150125000000"]
};
var result = data.root.children.filter(function (o) {
return o.name === filterBy.name[0] && o.order[0].startTime === filterBy.startTime[0] && o.order[0].endTime === filterBy.endTime[0];
});
console.log(result);
I need to take the data from below mentioned array of object which has maximum length of nested array object. As per below my request, id : 2 values has 3 objects, result will be as mentioned below.
Anyone help me using lodash or some javascript function to achieve this.
Sample Request:
[{
"id": 1,
"values": [
{
"sub": "fr",
"name": "foobar1"
},
{
"sub": "en",
"name": "foobar2"
}
]
},
{
"id": 2,
"values": [
{
"sub": "fr",
"name": "foobar3"
},
{
"sub": "en",
"name": "foobar4"
},
{
"sub": "ts",
"name": "foobar5"
},
]
}]
Expected output:
"values": [
{
"sub": "fr",
"name": "foobar3"
},
{
"sub": "en",
"name": "foobar4"
},
{
"sub": "ts",
"name": "foobar5"
},
]
}]
This can be achieved using the native javascript reduce function as follows
var source = [...];
source.reduce((max, cur) => cur.values.length > max.values.length ? cur : max, source[0])
So I'm having an issue - I'm getting some data from our internal API at work, but it's not in the correct format I need to do what I have to do, so I have to make some transformations.
For this, I decided to use Lodash, however I'm stuck now.
Basically, I'm working with orders, but some of the products are addons to a parent product. I've managed so far to separate these two types of products, but I don't know how I should go about adding an "addons" array as a child to the parent product with matching ID.
Here's a basic stripped example of the output I'd like:
{
"order": {
"orderLines: [
{
"orderId": "foo",
"addons" [
{
...
}
]
},
{
...
}
]
}
}
And here's my current code:
// TODO:
// Match addons to products based on "connectedTo" => "id", then add matching addons as a new array on parent object
// Base data
const data = {
"order": {
"shopOrderId": "19LQ89H",
"createDate": "2017-10-24T13:09:22.325Z",
"orderLines": [
{
"orderId": "19LQ89H",
"product": {
"productName": "Paintball",
},
"id": "59ef3b8036e16f1c84787c1f",
"stringId": "59ef3b8036e16f1c84787c1f"
},
{
"orderId": "19LQ89H",
"product": {
"productName": "Ølsmagning",
},
"id": "59ef3b8036e16f1c84787c20",
"stringId": "59ef3b8036e16f1c84787c20"
},
{
"orderId": "19LQ89H",
"product": {
"productName": "CD-indspilning",
},
"id": "59ef3b8136e16f1c84787c21",
"stringId": "59ef3b8136e16f1c84787c21"
},
{
"orderId": "19LQ89H",
"product": {
"productName": "Julefrokost",
},
"id": "59ef3b8236e16f1c84787c22",
"stringId": "59ef3b8236e16f1c84787c22"
},
{
"orderId": "19LQ89H",
"product": {
"productName": "Hummer Limousine",
},
"id": "59ef3b8236e16f1c84787c23",
"stringId": "59ef3b8236e16f1c84787c23"
},
{
"orderId": "19LQ89H",
"connectedTo": "59ef3b8236e16f1c84787c23",
"product": {
"productName": "Ekstra kørsel 400",
},
"id": "59ef3b8236e16f1c84787c24",
"stringId": "59ef3b8236e16f1c84787c24"
},
{
"orderId": "19LQ89H",
"connectedTo": "59ef3b8236e16f1c84787c23",
"product": {
"productName": "Drikkevarer",
},
"id": "59ef3b8236e16f1c84787c25",
"stringId": "59ef3b8236e16f1c84787c25"
},
{
"orderId": "19LQ89H",
"connectedTo": "59ef3b8236e16f1c84787c23",
"product": {
"productName": "Drikkevarer",
},
"id": "59ef3b8236e16f1c84787c26",
"stringId": "59ef3b8236e16f1c84787c26"
},
{
"orderId": "19LQ89H",
"connectedTo": "59ef3b8236e16f1c84787c22",
"product": {
"productName": "Snaps ad libitum",
},
"id": "59ef3b8236e16f1c84787c27",
"stringId": "59ef3b8236e16f1c84787c27"
}
],
"travelTimes": [
{
"id": "59ef3b8036e16f1c84787c1f-59ef3b8036e16f1c84787c20",
"partyPlanFromEventId": "59ef3b8036e16f1c84787c1f",
"partyPlanToEventId": "59ef3b8036e16f1c84787c20",
"start": "2017-11-15T17:02:59",
"end": "2017-11-15T17:30:00",
"travelTimeString": "27 min.",
"travelTimeMinutes": 28,
"exceedsAvailableTime": false
},
{
"id": "59ef3b8036e16f1c84787c20-59ef3b8136e16f1c84787c21",
"partyPlanFromEventId": "59ef3b8036e16f1c84787c20",
"partyPlanToEventId": "59ef3b8136e16f1c84787c21",
"start": "2017-11-15T19:52:12",
"end": "2017-11-15T20:00:00",
"travelTimeString": "8 min.",
"travelTimeMinutes": 8,
"exceedsAvailableTime": false
},
{
"id": "59ef3b8036e16f1c84787c20-59ef3b8236e16f1c84787c22",
"partyPlanFromEventId": "59ef3b8036e16f1c84787c20",
"partyPlanToEventId": "59ef3b8236e16f1c84787c22",
"start": "2017-11-15T12:30:00",
"end": "2017-11-15T13:00:00",
"travelTimeString": "8 min.",
"travelTimeMinutes": 8,
"exceedsAvailableTime": true
},
{
"id": "59ef3b8036e16f1c84787c20-59ef3b8236e16f1c84787c23",
"partyPlanFromEventId": "59ef3b8036e16f1c84787c20",
"partyPlanToEventId": "59ef3b8236e16f1c84787c23",
"start": "2017-11-15T08:30:00",
"end": "2017-11-15T09:00:00",
"travelTimeString": "3 min.",
"travelTimeMinutes": 4,
"exceedsAvailableTime": true
}
],
"id": "59ef3b8236e16f1c84787c28",
"stringId": "59ef3b8236e16f1c84787c28"
}
}
// Transform data
const travelTimes = data.order.travelTimes.map(item => _.omit(item, ['id']) )
const orderLines = _.merge(data.order.orderLines, travelTimes)
const order = _.omit(data.order, ['orderLines', 'travelTimes'])
const orders = _.assign(order, { orderLines })
const addonGroups = _.groupBy(order.orderLines, 'connectedTo')
const addons = _.omit(addonGroups, 'undefined')
const products = _.pick(addonGroups, 'undefined')
const productGroups = _.groupBy(products.undefined, 'stringId')
console.log(productGroups) // All parent products
console.log(addons) // All addon products
const arr1 = _.values(_.flatMap(productGroups))
const arr2 = _.values(_.flatMap(addons))
Code on Codepen.io
Any help is greatly appreciated!
Let me know if I need to explain in further detail.
Not sure if I understood correctly what the expected result is, but I gave it a try anyway.
const orderLines = _(data.order.orderLines)
.map(item => {
if (!item.connectedTo) return _.assignIn(item, { addons: [] });
const match = _.find(data.order.orderLines, { id: item.connectedTo });
match.addons = match.addons || [];
match.addons.push(item);
return null;
})
.compact()
.value();
Check the output here: https://codepen.io/andreiho/pen/YEzQRd?editors=0012