Wrong results when property name equals search value - javascript

I am using Breeze.js in my project and the following query returns me all the group entities that I have in local cache although only one of them has group==group
breeze.EntityQuery.from('Groups').using(manager).where('group', '==', 'group').executeLocally();
Here my metadata definition:
{
"shortName": "Group",
"namespace": "CM.Models",
"baseTypeName": "Entity",
"autoGeneratedKeyType": "Identity",
"defaultResourceName": "Groups",
"dataProperties": [
{
"name": "groupID",
"dataType": "String",
"maxLength": 32,
"defaultValue": "",
"validators": [
{
"name": "maxLength",
"maxLength": 32
}
]
},
{
"name": "group",
"dataType": "String",
"maxLength": 32,
"defaultValue": "",
"validators": [
{
"name": "required"
},
{
"name": "maxLength",
"maxLength": 32
}
]
},
{
"name": "groupMembers",
"dataType": "String",
"isScalar": false,
"defaultValue": []
}
]
}
Is it a bug of Breeze.js?

For reference, I found the answer after digging into breeze.js code. It turns out that it is possible to escape the evaluation side. Therefore the query becomes:
breeze.EntityQuery.from('Groups').using(manager).where('group', '==', "'group'").executeLocally();
"'group'" insetad 'group'

Related

How to Restructure/Translate Json objects to satisfy any schema?

I have a (long) json schema and I already validate the json objects in my code based on that schema.
My problem/use-case is to translate/restructure an incoming json object to a new json object that satisfies my schema.
I realized however, that it isn't that easy to do, especially if you look for an "adaptive" solution.
Adaptive meaning that the code doesn't care about changes of the schema or the incoming object.
So my first approach was to create a class that contains a mapping of the incoming object to a valid object.
This means however that I have to write this map by hand and update it if I change the schema.
So is there a solution where I can insert any schema, any non-valid (based on schema) json object and get a valid object out?
Or at-least a way to generate a valid json object template, where you can insert the data of the incoming invalid json object?
This way I could at least be independent from schema changes.
PS: I tried to solve this problem in an abstract way, but if needed I can provide schema and the invalid object.
PPS: My environment is node.js.
Edit: E.g.:
Schema
{
...//other Schema stuff (using draft-07)
"tokens": {
"$id": "/token",
"title": "Token",
"description": "A representation of a word in a Message with all the nlp Analysis results and infos",
"type": "array",
"minItems": 1,
"items": {
"$ref": "#/definitions/tokens/definitions/token"
},
"token": {
"$id": "#token",
"type": "object",
"required": [
"id",
"text"
],
"properties": {
"id": {
"description": "global (level:conversation) unique identifier to identify a token (cumulative)",
"type": "number",
"exclusiveMinimum": 0,
"uniqueItems": true
},
"isText": {
"description": "Describes if the token is a real semantic word or a whitespace or similar",
"type": "boolean"
},
"text": {
"description": "the actual content of the token",
"type": "string",
"pattern": "^(.+)$"
},
"word_index": {
"description": "Index of a word in a text",
"type": "number",
"exclusiveMinimum": 0,
"uniqueItems": true
},
"punctuation": {
"description": "The punctuation that needs to be rendered before/after that token. TODO: finish it",
"type": "string"
},
"characterOffsetBegin": {
"type": "integer",
"description": "The inclusive character index in the sentence where this token begins"
},
"characterOffsetEnd": {
"type": "integer",
"description": "The exclusive character index in the sentence where this token ends"
},
"lemma": {
"type": "string",
"pattern": "^(.+)$"
},
"pos": {
"type": "string",
"description": "part of speech tag",
"pattern": "^(.+)$"
},
}
},
"text_label": {
//This is where it gets difficult
"description": "Label of the text for the frontend. ",
"type": "object",
"required": [
"name",
"begin",
"end"
],
"additionalProperties": false,
"properties": {
"name": {
"description": "Name of the label",
"type": "string"
},
"begin": {
"description": "Token index where the label starts",
"type": "number"
},
"end": {
"description": "Token indes where the label ends",
"type": "number"
}
}
}
}
}
Object to translate:
{
"text": "Hello, my name is Somebody. ",
"sentences": [
{
"index": 0,
"tokens": [
{
"index": 1,
"word": "Hello",
"originalText": "Hello",
"characterOffsetBegin": 0,
"characterOffsetEnd": 5,
"before": "",
"after": "",
"pos": "UH",
"lemma": "hello"
},
{
"index": 2,
"word": ",",
"originalText": ",",
"characterOffsetBegin": 5,
"characterOffsetEnd": 6,
"before": "",
"after": " ",
"pos": ",",
"lemma": ","
},
{
"index": 3,
"word": "my",
"originalText": "my",
"characterOffsetBegin": 7,
"characterOffsetEnd": 9,
"before": " ",
"after": " ",
"pos": "PRP$",
"lemma": "my"
},
{
"index": 4,
"word": "name",
"originalText": "name",
"characterOffsetBegin": 10,
"characterOffsetEnd": 14,
"before": " ",
"after": " ",
"pos": "NN",
"lemma": "name"
},
{
"index": 5,
"word": "is",
"originalText": "is",
"characterOffsetBegin": 15,
"characterOffsetEnd": 17,
"before": " ",
"after": " ",
"pos": "VBZ",
"lemma": "be"
},
{
"index": 6,
"word": "Somebody",
"originalText": "Somebody",
"characterOffsetBegin": 18,
"characterOffsetEnd": 26,
"before": " ",
"after": "",
"pos": "NN",
"lemma": "somebody"
},
{
"index": 7,
"word": ".",
"originalText": ".",
"characterOffsetBegin": 26,
"characterOffsetEnd": 27,
"before": "",
"after": "",
"pos": ".",
"lemma": "."
}
],
"basicDependencies": []
}
]
}
Note: that this is corenlp analysis result that can change based on the annotator used.
Edit2: adding example of a correct object:
{ ...other parts of the object
tokens:[
{ id:1, text: 'Hello', isText: true, word_index: 0, characterOffsetBegin:0, characterOffsetEnd: 5, lemma: 'hello', pos:'UH', ...},
{...},
{...}
],
text_label:{
name: 'joy', begin: 0, end: 3
}
}
or another text_label:
text_label:{
name: 'PERSON', begin: 4, end: 5
}
Edit: Difference:
As you can see, some changes a suttle like index->word_index, some are additional information like id, but some need a bit more like the text_label.
corenlp. It could also happen that I need to unify 2 objects together. which is the case of the 'anger' text_label but isnt with the PERSON text_label.
So Im looking for some kind of json Object/Schema manager where translations, validations get easy and dont need hard coded mappings or the generation of that mappings is easy.

angular-schema-form array length

I have this schema:
{
"type": "object",
"title": "Comment",
"required": [
"comments"
],
"properties": {
"comments": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"title": "Name",
"type": "string"
},
"email": {
"title": "Email",
"type": "string",
"pattern": "^\\S+#\\S+$",
"description": "Email will be used for evil."
},
"spam": {
"title": "Spam",
"type": "boolean",
"default": true
},
"comment": {
"title": "Comment",
"type": "string",
"maxLength": 20,
"validationMessage": "Don't be greedy!"
}
},
"required": [
"name",
"comment"
]
}
}
}
}
This is an array of comments. I can add and remove comments.
How can I render 2 items of the array always by default ?
I've tried with maxItems and minItems but those parameters don't render items.
There are two ways to do it currently.
First is to set them in the default model so it looks something like:
$scope.model = {
"comments": [{},{}]
}
The second would be to use onChange on the array:
"onChange": function(val) { if(val.length < 2) val.push({}); }
The difference between the two being that the onChange will not allow it to drop below the minimum length you set while the first option is just for the initial default.

How to get "title" from AJV error?

I've got a JSON Schema that looks like this:
{
"required": [
"instructions"
],
"properties": {
"instructions": {
"title": "Instructions",
"minItems": 3,
"type": "array",
"items": {
"required": [
"typeId",
"teamId",
"disciplineId"
],
"properties": {
"typeId": {
"minimum": 1,
"title": "Appointment Type",
"type": "integer"
},
"teamId": {
"minimum": 1,
"title": "Team",
"type": "integer"
},
"disciplineId": {
"minimum": 1,
"title": "Discipline",
"type": "integer"
},
"prefClinicianId": {
"title": "Pref. Clinician",
"anyOf": [
{
"type": "null"
},
{
"minimum": 1,
"type": "integer"
}
]
},
"prefTime": {
"title": "Pref. Time",
"anyOf": [
{
"type": "null"
},
{
"type": "integer"
}
]
},
"childRequired": {
"title": "Child Req'd",
"type": "boolean"
}
},
"type": "object"
}
}
},
"type": "object"
}
As you can see, I've added titles to all the properties. However, the error object I get back looks like:
[
{
"keyword": "minItems",
"dataPath": ".instructions",
"schemaPath": "#/properties/instructions/minItems",
"params": {
"limit": 3
},
"message": "should NOT have less than 3 items"
},
{
"keyword": "type",
"dataPath": ".instructions[0].typeId",
"schemaPath": "#/properties/instructions/items/properties/typeId/type",
"params": {
"type": "integer"
},
"message": "should be integer"
},
{
"keyword": "type",
"dataPath": ".instructions[0].teamId",
"schemaPath": "#/properties/instructions/items/properties/teamId/type",
"params": {
"type": "integer"
},
"message": "should be integer"
},
{
"keyword": "type",
"dataPath": ".instructions[0].disciplineId",
"schemaPath": "#/properties/instructions/items/properties/disciplineId/type",
"params": {
"type": "integer"
},
"message": "should be integer"
}
]
As you can see, the title is not in there. How can I get the titles with the errors?
Please note that this question is specific to AJV.
When you create your AJV object set the verbose option to true.
This will add a parentSchema property to the ajv error with the original schema. It will also add a schema property that contains the specific schema attribute that caused the validation failure.
Here's an example:
var ajv = new Ajv({
$data: true,
verbose: true
});
let schema = {
title: 'object title',
type: 'object',
properties: {
str: {
title: "A string property",
type: "string"
}
}
};
let data = {
str: 3
};
ajv.validate(schema, data)
console.log('ERRORS: ', this.ajv.errors)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ajv/5.3.0/ajv.bundle.js"></script>

Loopback and MongoDB

I've been trying to create a collection that contains an array of objects in loopback.
I want a store data formatted like this:
{
id: "16356135616aaasad", //autogenerated by mongo
"name" : "a name",
"valores": [
{"valor": 567, "fecha": "2016-08-18T00:00:00.000Z"},
{"valor": 569, "fecha": "2016-08-19T00:00:00.000Z"},
...
]
}
I have the following configuration in loopback:
indicador.json
{
"name": "Indicador",
"plural": "indicadores",
"base": "PersistedModel",
"idInjection": true,
"options": {
"validateUpsert": true,
"autoId": true
},
"properties": {
"nombre": {
"type": "string",
"required": true
}
},
"relations": {
"historico": {
"type": "embedsMany",
"model": "Valor"
}
}
}
this is a base collection associated to another model (not persistent)
valor.json
{
"name": "Valor",
"plural": "valores",
"base": "Model",
"properties": {
"valor": {
"type": "number",
"required": true
},
"fecha": {
"type": "date",
"required": true
}
}
}
The problem it's when i try to send a post to the endpoint. If i send this data
{
"nombre": "UF",
"valores": [
{
"valor": 0,
"fecha": "2016-08-18"
}
]
}
The API responses this:
{
"error": {
"name": "ValidationError",
"status": 422,
"message": "The `Indicador` instance is not valid. Details: `valores` contains invalid item at index `0`: `id` is blank (value: [ { valor: 0, fecha: 2016...} ]).",
"statusCode": 422,
"details": {
"context": "Indicador",
"codes": {
"valores": [
"invalid"
]
},
"messages": {
"valores": [
"contains invalid item at index `0`: `id` is blank"
]
}
},
"stack": "ValidationError: The `Indicador` instance is not valid. Details: `valores` contains invalid item at index `0`: `id` is blank (value: [ { valor: 0, fecha: 2016...} ]).\n at /home/dev/app/node_modules/loopback-datasource-juggler/lib/dao.js:322:12\n at ModelConstructor.<anonymous> (/home/dev/app/node_modules/loopback-datasource-juggler/lib/validations.js:492:11)\n at ModelConstructor.next (/home/dev/app/node_modules/loopback-datasource-juggler/lib/hooks.js:81:12)\n at ModelConstructor.<anonymous> (/home/dev/app/node_modules/loopback-datasource-juggler/lib/validations.js:489:23)\n at ModelConstructor.trigger (/home/dev/app/node_modules/loopback-datasource-juggler/lib/hooks.js:71:12)\n at ModelConstructor.Validatable.isValid (/home/dev/app/node_modules/loopback-datasource-juggler/lib/validations.js:455:8)\n at /home/dev/app/node_modules/loopback-datasource-juggler/lib/dao.js:318:9\n at doNotify (/home/dev/app/node_modules/loopback-datasource-juggler/lib/observer.js:98:49)\n at doNotify (/home/dev/app/node_modules/loopback-datasource-juggler/lib/observer.js:98:49)\n at doNotify (/home/dev/app/node_modules/loopback-datasource-juggler/lib/observer.js:98:49)"
}
}
¿Why i get this error?
The id inside the objects of the array that I need isn't necessary for me. I don't understand why happen this.
You need to specify that embedded model doe not need id
"relations": {
"historico": {
"type": "embedsMany",
"model": "Valor",
"options": {
"forceId": false,
"validate": true,
"persistent": false
}
}
}
You need to add "defaultFn":"uuid" to the id property in the json of the model that is going to be embeded in order to have the id generated. In your case it will look like the following:
{
"name": "Valor",
"plural": "valores",
"base": "Model",
"properties": {
"id":{
"type": "string",
"defaultFn":"uuid",
"id":true
},
"valor": {
"type": "number",
"required": true
},
"fecha": {
"type": "date",
"required": true
}
}
}

How do I console.log one value of this JSON Object?

I am new to javascript and to JSON, so please forgive me.
If I have the following JSON Object, how would I console.log() out the value of autonum?
{
"database": "testdb",
"table": "path",
"affectedColumns": [
{
"name": "autonum",
"charset": null,
"type": 8
},
{
"name": "TimeStamp",
"charset": null,
"type": 18,
"metadata": {
"decimals": 0
}
},
{
"name": "FilePath",
"charset": "latin1",
"type": 15,
"metadata": {
"max_length": 256
}
},
{
"name": "DirPath",
"charset": "latin1",
"type": 15,
"metadata": {
"max_length": 256
}
},
{
"name": "DirName",
"charset": "latin1",
"type": 15,
"metadata": {
"max_length": 256
}
},
{
"name": "EventName",
"charset": "latin1",
"type": 15,
"metadata": {
"max_length": 256
}
},
{
"name": "FileName",
"charset": "latin1",
"type": 15,
"metadata": {
"max_length": 256
}
},
{
"name": "FileExt",
"charset": "latin1",
"type": 15,
"metadata": {
"max_length": 10
}
},
{
"name": "FileSize",
"charset": null,
"type": 3
},
{
"name": "MainFlag",
"charset": null,
"type": 1
},
{
"name": "DeleteFlag",
"charset": null,
"type": 1
},
{
"name": "Status",
"charset": "latin1",
"type": 15,
"metadata": {
"max_length": 255
}
},
{
"name": "ProcessedFlag",
"charset": null,
"type": 1
}
],
"changedColumns": [],
"fields": {
"autonum": 121,
"TimeStamp": "2016-01-13T00:21:13.000Z",
"FilePath": "c:/1E0304F120151223030158001.mp4",
"DirPath": "c:\\",
"DirName": null,
"EventName": null,
"FileName": "1E0304F120151223030158001.mp4",
"FileExt": ".mp4",
"FileSize": 2218108,
"MainFlag": 0,
"DeleteFlag": 0,
"Status": null,
"ProcessedFlag": 0
}
}
Depending on which autonum you want, and assuming your variable storing the JSON is data, you'll want to do something as follows:
console.log(data.fields.autonum);
or
console.log(data.affectedColumns[0].name);
You'd use the following code, assuming the json object is called record:
console.log(record.fields.autonum);
You have two main ways of doing it. Both are correct ways. Lets say your object is named obj. Use console.log as following:
console.log(obj.fields.autonum)
console.log(obj['fields']['autonum'])
First case is easier as compare to second case.
Second case is safer as it will allow you to even take care of keys which have spaces e.g.
var my_other_object = {
'Santa Clara': 'USA',
'Toronto': 'Canada'
};
console.log(my_other_object['Santa Clara']) // Output will be 'USA'
For your understanding, in above object 'Santa Clara' and 'Toronto' are called 'keys' of my_other_object and 'USA', 'Canada' are called 'values' of those 'keys'.
So JSON object is essentially combination of key:value pairs.
P.S. Never apologize while asking a question all questions are valid but it is good to always search before asking. Still, people are always happy to help here. We all have went through same phases. :)
Lets say your object name var data, then data.fields.autonum would give us value 121
console.log(data.fields.autonum)
Just FYI:
As it is stated on MDN website:
some JavaScript is not JSON, and some JSON is not JavaScript
Just in order to improve understanding of vocabulary, 'JSON Object' is not a thing in our context ... it is
a syntax for serializing objects

Categories