How to search array of objects by id when that id is within another array (JsonPath)? - jsonpath

I'm trying to use JsonPath to filter an array of objects by id. For each item in the array I want to filter it if its id is in a second array.
So for example I have the source array:
[
{
id: 1,
name: "House"
},
{
id: 2,
name: "Hamer"
},
{
id: 13,
name: "Book"
},
{
id: 45,
name: "Truck"
},
]
And I want to filter this array by id, if that id is in another array, for example:
[ 2, 13]
This should result in a filtered array of:
[
{
id: 2,
name: "Hamer"
},
{
id: 13,
name: "Book"
}
]
I can figure out how to do this with a lengthy or statement with each item in the second array, but that seems like a pretty painful and silly way to filter one array by another.
How can I perform the above operation using JsonPath, but without an or for each array item in the second array?

getItemsById = (arr, arr2) => {
result = arr.filter(f => arr2.includes(f.id));
console.log(result);
}

Related

How do I extract out the data from this array of arrays of objects

I am getting out data from a database, and because the database contains more than one recordset, it is ending up with output like this:
[
[ { TotalRecords: 11873 } ],
[
{
ProductID: 12394,
ProductTitle: 'XYZ1'
},
{
ProductID: 14282,
ProductTitle: 'XYZ2'
},
{
ProductID: 11405,
ProductTitle: 'XYZ3'
},
{
ProductID: 12467,
ProductTitle: 'XYZ4'
}
]
]
I pass all that data to my view (Handlebars) as an object called products. How can I loop around the second array which contains the ProductID and ProductTitle information to display it on a page?
Provided that the position is known, you can iterate over the second array by this:
{{#each products.[1]}}
<p>{{ProductID}}: {{ProductTitle}}</p>
{{/each}}
Note the [1] which specifies the index number.

Firebase-Dart Filtering Data

My data is something like this:
{
"members": [
{
"type": "alpha",
"name": "John"
},
{
"type": "alpha",
"name": "Jane"
},
{
"type": "beta",
"name": "Renata"
},
{
"type": "beta",
"name": "Richard"
}
]
}
If I access it as follows, I get the list of all members:
DatabaseReference ref = database().ref('members')
ref.onValue.listen((e) {
var members = e.snapshot.val();
});
However, if I try to filter the data, as follows, I get null.
DatabaseReference ref = database().ref('members').orderByValue().equalTo("alpha", "type");
ref.onValue.listen((e) {
var members = e.snapshot.val();
});
How do I get only objects with "type" "alpha"?
Your members reference corresponds to a List of objects, and none of the immediate children in the List are strings like "alpha" so your orderByValue().equalTo() query returns null. The "type" argument you're passing is searching on indices in the list (0, 1, etc.) rather than keys in the child objects ("type", "name").
Instead, you can use orderByChild():
DatabaseReference ref = database().ref().child('members').orderByChild("type").equalTo("alpha");
You may find that you get a List with some holes in it, if the alphas aren't at the beginning:
[{name: John, type: alpha}, null, {name: Jane, type: alpha}]
You can remove the null values with
members = new List<Object>.from(members)..remove(null);

Normalizr - Setting key of nested responses in results

I see in the normalizer examples that they have a name property "users" being returned on the results object:
{
result: { users: [ 1, 2 ] },
entities: {
users: {
'1': { id: 1 },
'2': { id: 2 }
}
}
}
I can't seem to figure out how to do this with the nested api response I'm getting. I have both a user and an address reducer that I am trying to pass the results of the normalized response into.
I have a JSON response that looks like this:
[
{
id: 1
first_name: First,
last_name: Last,
address: {
data: [
{
id: 1,
address_one: '123 Street Ave',
address_two: '',
city: 'Some City',
state: 'CA',
zip: '1234'
}
]
}
},
{
id: 1
first_name: First,
last_name: Last,
address: {
data: [
{
id: 2,
address_one: '123 Street Ave',
address_two: '',
city: 'Some City',
state: 'CA',
zip: '1234'
},
{
id: 3,
address_one: '321 Avenue Road',
address_two: 'Suite 101',
city: 'Some City',
state: 'CA',
zip: '1234'
}
]
}
}
]
My schema looks like this:
import { schema } from 'normalizr'
/**
* Addresses
*/
const address = new schema.Entity('addresses');
const arrayOfAddresses = new schema.Array(address);
/**
* User
*/
export const user = new schema.Entity('users', {
addresses: arrayOfAddresses
});
user.define({
addresses: {
data: arrayOfAddresses
}
})
export const arrayOfUsers = new schema.Array(user)
Doing: let result = normalize(data, schema.arrayOfUseres)
returns:
{
entities: {
addresses: /* The address data */
users: /* The users with an array of the address ids attached to them*/
},
result: [1, 2]
}
What I would really like is the result object to have both the users and the addresses in it:
{
entities: {
addresses: /* The address data */
users: /* The users with an array of the address ids attached to them */
},
result: {
addresses: [1, 2, 3]
users: [1, 2]
}
}
Is this possible? I've tried several variations of
import * as schema from './schema'
normalize(data, { users: [schema.user], addresses: [schema.address] }
But this just errors out and returns my data back into the result object.
Is this possible?
No. The result value is always set to match the top structure of your input data per the schema. If your input data doesn't have a first-level key addresses, it won't be possible.

Collection id: By index or by value?

Maybe I don't know what to search for this, but I tried "[json] id as index or value".
I am curious what others' experience teaches regarding this. I have a number of rest calls that return JSON data from a database. Among the values, are unique identifiers. My question is,
Is it better to provide the IDs as fields on the items, or as an index on items. For example:
{
dataByValue: [
{ id: 1, data: "What's up?", otherData: "hi" },
{ id: 2, data: 123, otherData: "hi" }
],
dataByIndex: {
1: { data: "What's up?", otherData: "hi" },
2: { data: 123, otherData: "hi" }
},
orMaybeBoth: {
1: { id: 1, data: "What's up?", otherData: "hi" },
2: { id: 2, data: 123, otherData: "hi" }
}
}
I realize this is not valid JSON, but you get the picture.
I have some thoughts on why each may be beneficial:
By value may be easier to loop through, especially on platforms that don't have an easy way to handle variable keys on objects.
By index allows you to quickly access the data if you do have the ID.

Any way to have Simple Schema in Meteor validate a specific array index?

From what I understand in the docs, you can define your schema like this:
MySchema = new SimpleSchema({
//This says that the addresses key is going to contain an array
addresses: {
type: [Object],
},
// To indicate the presence of an array, use a $:
"addresses.$.street": {
type: String,
},
"addresses.$.city": {
type: String,
}
});
Ok, I get this part. But what if I wanted to validate the contents in a specific array index? I want something like this:
MySchema = new SimpleSchema({
//This says that the itemsOrdered key is going to contain an array
itemsOrdered: {
type: [Object],
},
// Here I want to validate certain indexes in the array.
"itemsOrdered.0.sku": {
type: String
},
"itemsOrdered.0.price": {
type: Number
},
"itemsOrdered.1.sku": {
type: String
},
"itemsOrdered.1.price": {
type: Number
},
"itemsOrdered.1.quantity": {
type: Number
},
"itemsOrdered.2.sku": {
type: String
},
"itemsOrdered.2.price": {
type: Number
},
"itemsOrdered.2.customerNotes": {
type: String
optional: true
}
});
So here I'm trying to validate the values inside array index 0, 1, and 2. Each array index has a different item that has been ordered.
Normally I would use a hash table data structure, but for this purpose I need to preserve order which is why I'm using an array.
When I try to run this code I get an error Cannot read property 'blackbox' of undefined
Have you considered custom validation?
https://github.com/aldeed/meteor-simple-schema/blob/master/README.md#custom-validation
According to the doc within the function the key property of this will provide the information you want. So you could have something like:
MySchema = new SimpleSchema({
//This says that the itemsOrdered key is going to contain an array
itemsOrdered: {
type: [Object],
},
// Here I want to validate certain indexes in the array.
"itemsOrdered.$.sku": {
type: String,
custom: function () {
var key = this.key,
re = /\d+/;
var index = Number(key.match(re)[0]);
// Do some custom validation
}
},
"itemsOrdered.$.price": {
type: Number
},
"itemsOrdered.$.quantity": {
type: Number,
optional: true
},
"itemsOrdered.$.customerNotes": {
type: String,
optional: true
}
});
Here I put the validation logic in the sku field since it's required.

Resources