Try to understand normalizr's schema.entity VS Array and Object - normalizr

All:
I am trying to understand the relationship between Entity Array and Object:
Are they just different format to describe diff structure of data? Or Entity is quite diff from the rest two?
The normalized data result has a structure like {result:,entities:}, are the data structures only defined with schema.Entity put inside entities or so can schema.Array and Object? When I define a schema only use Object and Array, it seems nothing put in entities, I am not sure if it is my schema def fault or this is how normalizr work?
If only schema.Entity() defined data can put into entities, then how can I put an data array into it, something like {0:.., 1:..,2:,}?
For exmaple, I have data like:
var data = [
{
id:"0",
items:[
{
id: "0",
data: {name:"data-0-0"}
},
{
id: "1",
data: {name:"data-0-1"}
}
]
},
{
id:"1",
items:[
{
id: "0",
data: {name:"data-1-0"}
},
{
id: "1",
data: {name:"data-1-1"}
}
]
}
]
const normalizedData = normalize(data, [{items:[{data:{}}]}]);
And the normalized data is like:
{
"entities": {},
"result": {
"0": {
"id": "0",
"items": [
{
"id": "0",
"data": {
"name": "data-1-0"
}
}
]
}
}
}
Thanks

Question: Are they just different format to describe diff structure of data? Or Entity is quite diff from the rest two?
Answer: Yes. An Entity is a singular object that has a unique identifier associated with it. Array and Object are more generic structures that can't be uniquely identified. In your case, it looks like you only need to use Array and Entity for the data you're describing.
Question: Are the data structures only defined with schema? Entity put inside entities?
Answer: Yes.

Related

How to describe a model in Swagger for an array with simple objects?

I have a REST service to document, and some of them accept simple array like:
[
{ "name":"a" },
{ "class":"b" },
{ "hello":"c" }
]
How do I describe this in the Swagger yaml model section? I can only create 'is_sellerarray' like
{
"is_seller": [
{
"name": "string",
"asim": "string"
}
]
}
You can define your own array type. Your Pet object will have name and asim as two attributes. Follow documents for more information. https://swagger.io/docs/specification/data-models/
type: array
items:
$ref: '#/components/schemas/Pet'
You can play around online swagger editor to see real time changes.
https://editor-next.swagger.io/

Match keys with sibling object JSONATA

I have an JSON object with the structure below. When looping over key_two I want to create a new object that I will return. The returned object should contain a title with the value from key_one's name where the id of key_one matches the current looped over node from key_two.
Both objects contain other keys that also will be included but the first step I can't figure out is how to grab data from a sibling object while looping and match it to the current value.
{
"key_one": [
{
"name": "some_cool_title",
"id": "value_one",
...
}
],
"key_two": [
{
"node": "value_one",
...
}
],
}
This is a good example of a 'join' operation (in SQL terms). JSONata supports this in a path expression. See https://docs.jsonata.org/path-operators#-context-variable-binding
So in your example, you could write:
key_one#$k1.key_two[node = $k1.id].{
"title": $k1.name
}
You can then add extra fields into the resulting object by referencing items from either of the original objects. E.g.:
key_one#$k1.key_two[node = $k1.id].{
"title": $k1.name,
"other_one": $k1.other_data,
"other_two": other_data
}
See https://try.jsonata.org/--2aRZvSL
I seem to have found a solution for this.
[key_two].$filter($$.key_one, function($v, $k){
$v.id = node
}).{"title": name ? name : id}
Gives:
[
{
"title": "value_one"
},
{
"title": "value_two"
},
{
"title": "value_three"
}
]
Leaving this here if someone have a similar issue in the future.

Apollo Server, typing an array of differently shaped objects

I am building a GraphQL layer on top of an existing REST api. In the schema, I have a key, "steps" that returns an array of differently shaped objects, of which one is an array of objects, like this
"steps": [
{
"created_at": "a string",
"created_by": "a string",
"event_name": "a string",
"reason": "failed",
},
{
"components": [
{
"condition": false,
"data": {
"address": "foo",
"address_city": "bar",
"address_state": "baz",
},
}
],
I am able to get the first object returning, but am struggling with how to type this in order to access the components array, which is coming back as null in the graphQL playground. In my typeDefs, I am typing like this
type Steps {
event_name: String
reason: String
created_at: String
created_by: String
step_date: String
step_name: String
components: [Components]
}
I understand WHY it's failing, as components is nested one extra level in it's own object, but I'm not sure what the fix is, since I can't just use a nested object in the type declaration and the individual objects in the steps array don't have keys.
Reading around the GraphQL docs, I can't see anything that explains how to type this sort of structure?

How to create a HashMap with custom object as a key?

In Elasticsearch, I have an object that contains an array of objects. Each object in the array have type, id, updateTime, value fields.
My input parameter is an array that contains objects of the same type but different values and update times. Id like to update the objects with new value when they exist and create new ones when they aren't.
I'd like to use Painless script to update those but keep them distinct, as some of them may overlap. Issue is that I need to use both type and id to keep them unique. So far I've done it with bruteforce approach, nested for loop and comparing elements of both arrays, but I'm not too happy about that.
One of the ideas is to take array from source, build temporary HashMap for fast lookup, process input and later store all objects back into source.
Can I create HashMap with custom object (a class with type and id) as a key? If so, how to do it? I can't add class definition to the script.
Here's the mapping. All fields are 'disabled' as I use them only as intermidiate state and query using other fields.
{
"properties": {
"arrayOfObjects": {
"properties": {
"typ": {
"enabled": false
},
"id": {
"enabled": false
},
"value": {
"enabled": false
},
"updated": {
"enabled": false
}
}
}
}
}
Example doc.
{
"arrayOfObjects": [
{
"typ": "a",
"id": "1",
"updated": "2020-01-02T10:10:10Z",
"value": "yes"
},
{
"typ": "a",
"id": "2",
"updated": "2020-01-02T11:11:11Z",
"value": "no"
},
{
"typ": "b",
"id": "1",
"updated": "2020-01-02T11:11:11Z"
}
]
}
And finally part of the script in it's current form. The script does some other things, too, so I've stripped them out for brevity.
if (ctx._source.arrayOfObjects == null) {
ctx._source.arrayOfObjects = new ArrayList();
}
for (obj in params.inputObjects) {
def found = false;
for (existingObj in ctx._source.arrayOfObjects) {
if (obj.typ == existingObj.typ && obj.id == existingObj.id && isAfter(obj.updated, existingObj.updated)) {
existingObj.updated = obj.updated;
existingObj.value = obj.value;
found = true;
break;
}
}
if (!found) {
ctx._source.arrayOfObjects.add([
"typ": obj.typ,
"id": obj.id,
"value": params.inputValue,
"updated": obj.updated
]);
}
}
There's technically nothing suboptimal about your approach.
A HashMap could potentially save some time but since you're scripting, you're already bound to its innate inefficiencies... Btw here's how you initialize & work with HashMaps.
Another approach would be to rethink your data structure -- instead of arrays of objects use keyed objects or similar. Arrays of objects aren't great for frequent updates.
Finally a tip: you said that these fields are only used to store some intermediate state. If that weren't the case (or won't be in the future), I'd recommend using nested arrays to enable querying independently of other objects in the array.

Find matching array items in MongoDB document

I am developing a web app using Codeigniter and MongoDB.
In the database I got a document that look like this:
{
"_id": {
"$id": "4f609932615a935c18r000000"
},
"basic": {
"name": "The project"
},
"members": [
{
"user_name": "john",
"role": "user",
"created_at": {
"sec": 1331730738,
"usec": 810000
}
},
{
"user_name": "markus",
"role": "user",
"created_at": {
"sec": 1331730738,
"usec": 810000
}
}
]
}
I need to search this document using both user_name and role. Right now when I am using the below code I get both. I only want to get array items matching both user_name and role.
$where = array (
'_id' => new MongoId ($account_id),
'members.user_id' => new MongoId ($user_id),
'members.role' => $role
);
$this -> cimongo -> where ($where) -> count_all_results ('accounts');
This is an old question, but as of MongoDB 2.2 or so you can use the $ positional operator in a projection so that only the matched array element is included in the result.
So you can do something like this:
$this->cimongo->where($where)->select(array('members.$'))->get('accounts');
This is a repeat of this question:
Get particular element from mongoDB array
Also you might want to use $elemMatch
http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-ValueinanArray
Here is the rub -- you aren't going to be able to get the array items that match because mongo is going to return the entire document if those elements match. You will have to parse out the code client side. Mongo doesn't have a way to answer, "return only the array that matches."

Resources