How to make a post API for mongodb with loopback - mongodb

I am newbie with mongodb and loopback. I want to send and save data from my app to database. how can I do that?
Update
shops model:
{
"shopname": "string",
"tel": "string",
"latlng": "string",
"address": "string",
"id": "string",
"personId": "string"
}
CURL:
curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' -d '{ \
"shopname": "spring", \
"tel": "12345678", \
"latlng": "52.1106986,21.7768998", \
"address": "05-319 Skwarne, Poland" \
}' 'http://localhost:3000/api/shops'
Now what should I write in shops.js to give an api for using in app to send data to database ?
'use strict';
module.exports = function(Shops) {
};

you should have provided more info about the steps you have already done.
let me begin with the first step:
download and install mongodb on your server: link
after running mongodb, add your desired database info to datasources.json file. e.g.
{
"db": {
"name": "db",
"connector": "memory"
},
"shopDB": {
"host": "localhost",
"port": 27017,
"url": "mongodb://localhost:27017/shopDB",
"database": "shopDB",
"password": "",
"name": "shopDB",
"user": "",
"connector": "mongodb"
}
}
add loopback-connector-mongodb to your project via npm.
now define your model(you can utilize loopback's user friendly command line interface to do so. call command "slc loopback:model" in your projects root folder)
after you finish the step 4, loopback will create 2files for you: shop.js and shop.json => these files are located in your projectFolder/common/models/ directory. note that it's a good practice to follow the loopback's convention in naming models and name your model in singular form(shop). (it uses the plural forms of the model names in other parts of the project). your shop.json should look like the below code:
{
"name": "shop",
"plural": "shops",
"base": "PersistedModel",
"idInjection": true,
"options": {
"validateUpsert": true
},
"properties": {
"shopname": {
"type": "string",
"required": true
},
"tel": {
"type": "string",
"required": true
},
"latlng": {
"type": "string",
"required": true
},
"address": {
"type": "string"
},
"personId": {
"type": "string",
"required": true
}
},
"validations": [],
"relations": {},
"acls": [],
"methods": {}
}
now you can post your shop json to http://localhost:3000/api/shops/ . note that our shop model inherits from PersistedModel base model and has some built-in functions to do crud operations. and if you want just create some shop instances in your db, you won't need to add anything to your shop.js file!

Related

Posting to orion gets me to "Attribute must be a JSON object"

I am sending this to Orion:
curl --location --request POST 'http://xx.xx.xx.xx:1026/ngsi-ld/v1/entities/' \
--header 'link: <https://smartdatamodels.org/context.jsonld>; rel="http://www.w3.org/ns/json-ld#context"; type="application/ld+json"' \
--header 'Content-Type: application/json' \
--data-raw '{
"id": "urn:ngsi-ld:Device:01",
"type": "Device",
"description": "L9A",
"category": {
"value": ["sensor"]
},
"serialNumber": {
"value": "38479144"
},
"controlledProperty": {
"value": ["Water Supply"]
},
"owner": {
"value": ["Me"]
},
"location": {
"type": "Point",
"coordinates": [20.200416, 30.261837]
}
}'
and I get this:
Error 400: Bad Request
{
"type": "https://uri.etsi.org/ngsi-ld/errors/BadRequestData",
"title": "Attribute must be a JSON object",
"detail": "description"
}
I validated by json object and it passes. What am I doing wrong?
Look a little closer at your error message, especially:
detail": "description"
That's the name of the attribute that is not a JSON object:
"description": "L9A"
If you change it to:
"description": {
"type": "Property",
"value": "L9A"
}
that part should be OK.
But, the type member seems to be missing for all your attributes.
you'll need to add "type": "Property" to all of them, except "location" that's a GeoProperty:
"location": {
"type": "GeoProperty",
"value": {
"type": "Point",
"coordinates": [20.200416, 30.261837]
}
}
Perhaps spend some time reading the NGSI-LD specification?
https://www.etsi.org/deliver/etsi_gs/CIM/001_099/009/01.04.02_60/gs_CIM009v010402p.pdf

Unable to delete Apache Atlas Classification

I have a list of Classifications & Sub-classifications in Apache Atlas. Want to delete them & create a new list.
All the other classifications are getting deleted but one of them with name "PII" giving following error when we select Delete Classification.
Error: Given type PII has references
When we do a search via Rest API using below URL:
http://ip.of.atlas:21000/api/atlas/v2/search/basic?classification=PII
Following Result comes:
{
"queryType": "BASIC",
"searchParameters": {
"classification": "PII",
"excludeDeletedEntities": false,
"includeClassificationAttributes": false,
"includeSubTypes": true,
"includeSubClassifications": true,
"limit": 100,
"offset": 0
},
"entities": [
{
"typeName": "hive_table",
"attributes": {
"owner": "nifi",
"createTime": 1557832055000,
"qualifiedName": "demo.test_table#demopilot",
"name": "test_table"
},
"guid": "ecb7bb24-bdde-448c-b718-07273e5ce572",
"status": "DELETED",
"displayText": "test_table",
"classificationNames": [
"PII"
],
"meaningNames": [],
"meanings": []
},
{
"typeName": "hive_table",
"attributes": {
"owner": "nifi",
"createTime": 1557832055000,
"qualifiedName": "demo.test_table#demopilot",
"name": "test_table"
},
"guid": "ed5a9284-c290-4431-ab76-27b820478e29",
"status": "DELETED",
"displayText": "test_table",
"classificationNames": [
"PII"
],
"meaningNames": [],
"meanings": []
},
{
"typeName": "hive_column",
"attributes": {
"owner": "nifi",
"qualifiedName": "demo.test_table.traffic_case#demopilot",
"name": "traffic_case"
},
"guid": "73f75a6c-9f4e-41f0-b0ef-6c05ca132639",
"status": "DELETED",
"displayText": "traffic_case",
"classificationNames": [
"PII"
],
"meaningNames": [],
"meanings": []
}
]
}
Questions:
1. Is there a API which help to delete all Classifications irrespective of whether they are attached to Entity or not?
2. Delete Single Classification forcefully with Classification Name or GUID?
Running below GET request:
http://ip.of.atlas:21000/api/atlas/v2/types/typedefs
& then Delete the guid attached to the typedefs
I tested it out and you could use below API to delete a tag:
curl -k -X DELETE --insecure --negotiate -u : --header \
''{"classificationDefs":[{"name":"PII","superTypes":[],"attributeDefs":[]}]}' \
'https://atlas-host:21443/api/atlas/v2/types/typedefs?type=classification'

loopback w/ table schemas, not identifying schema in options

Nature of the issue
My db2 database makes wide use of table schemas for organization, so the table in question is LIVE.TBLADDRESS -
My model uses the "options" to specify the table schema
"options": {
"idInjection": false,
"db2": {
"schema": "LIVE",
"table": "TBLADDRESS"
}
}
the model is in the model-config.json using
,"Tbladdress": {
"dataSource": "x3",
"public": true
}
I get an error when I try to use the explorer to do a simple 'get' or any other API call.
"statusCode": 500,
"name": "Error",
"message": "[IBM][CLI Driver][DB2/LINUXX8664] SQL0204N "DB2X.TBLADDRESS" is an undefined name. SQLSTATE=42704\r\n",
Expected behavior
Once I specified the schema - I'd expect the API to resolve correctly
Actual behavior
The default schema for db user is used at all times...regardless of specified schema in options.
Suggested resolution
Maybe I set it in the wrong place, I will continue to look for the information, It is possible I am missing something.
This is what I "see" using DB Viewer...so you have an idea what I'm referring to.
DEV - host:50000/DEV
-schemas
|-AAA
|-BBB
|-DB2X (this is the schema that the error is referring to...but NOT the one specified in the model)
|-DDD
|-LIVE (this is the correct schema)
|--Tables
|--|-TBLA
|--|-TBLADDRESS
|-ZZZ
If it helps - this happens with manually create models or models generated by discovery scripts.
These are my config files, and model
/common/models/Tbladdress.json
{
"name": "Tbladdress",
"options": {
"idInjection": false,
"db2": {
"schema": "LIVE",
"table": "TBLADDRESS"
}
},
"properties": {
...
}
}
/datasources.json
{
"db": {
"name": "db",
"connector": "memory"
},
"x3": {
"name": "x3",
"connector": "db2",
"username": "...",
"password": "...",
"database": "...",
"hostname": "...",
"port": 50000
}
}
/model-config.json
{
"_meta": {
...
},
"User": {
"dataSource": "db"
},
"AccessToken": {
"dataSource": "db",
"public": false
},
"ACL": {
"dataSource": "db",
"public": false
},
"RoleMapping": {
"dataSource": "db",
"public": false,
"options": {
"strictObjectIDCoercion": true
}
},
"Role": {
"dataSource": "db",
"public": false
}
,"Tbladdress": {
"dataSource": "x3",
"public": true
}
}
http://localhost:3000/explorer/#!/Tbladdress/Tbladdress_findById
{
"error": {
"statusCode": 500,
"name": "Error",
"message": "[IBM][CLI Driver][DB2/LINUXX8664] SQL0204N \"DB2X.TBLADDRESS\" is an undefined name. SQLSTATE=42704\r\n",
"errors": [],
"error": "[node-ibm_db] SQL_ERROR",
"state": "42S02",
"stack": "Error: [IBM][CLI Driver][DB2/LINUXX8664] SQL0204N \"DB2X.TBLADDRESS\" is an undefined name. SQLSTATE=42704\r\n"
}
}
...Headers...
{
"date": "Sun, 18 Feb 2018 05:20:36 GMT",
"x-content-type-options": "nosniff",
"x-download-options": "noopen",
"x-frame-options": "DENY",
"content-type": "application/json; charset=utf-8",
"transfer-encoding": "chunked",
"connection": "keep-alive",
"access-control-allow-credentials": "true",
"vary": "Origin, Accept-Encoding",
"x-xss-protection": "1; mode=block"
}
USING:
loopback-cli v3 to generate express app
loopback-connector-db2 to connect to DB2 v10
Node v8.9.2
Package.JSON dependencies looks like this (as mentioned it's a default install, with one model added - to see if I could get it to work)
"dependencies": {
"compression": "^1.0.3",
"cors": "^2.5.2",
"helmet": "^1.3.0",
"loopback": "^3.0.0",
"loopback-boot": "^2.6.5",
"loopback-component-explorer": "^5.0.0",
"loopback-connector-db2": "^2.1.1",
"serve-favicon": "^2.0.1",
"strong-error-handler": "^2.0.0"
},
Yes - the DB2 connector worked fine when I specified the "LIVE" schema on data discovery - but it does NOT seem to be working when I use the API. I don't know if it's the connector or the loopback app.
For loopback-connector-db2, you must define SCHEMA in the datasources.json config file.
{
"x3": {
"name": "x3",
"connector": "db2",
"username": "...",
"password": "...",
"database": "...",
"hostname": "...",
"port": 50000
},
"x3Live": {
"name": "x3Live",
"connector": "db2",
"schema": "LIVE",
"username": "...",
"password": "...",
"database": "...",
"hostname": "...",
"port": 50000
}
}
Unfortunately, you will need to create a new datasource (e.g. x3Live). Use the old x3 datasource for the models using the DB2X schema, and the new x3Live datasource for the models using the LIVE schema.

How can I use the BigQuery REST API from the command line?

Attempting to make a plain GET request to one of the BigQuery REST APIs gives an error that looks like this:
curl https://www.googleapis.com/bigquery/v2/projects/$PROJECT_ID/jobs/$JOBID
Output:
{
"error": {
"errors": [
{
"domain": "global",
"reason": "required",
"message": "Login Required",
"locationType": "header",
"location": "Authorization",
...
What is the correct way to invoke one of the REST APIs from the command-line, such as the query or insert APIs? The API reference has a "Try this API", but the examples don't translate directly to something you can run from the command-line.
As a disclaimer, when working from the command-line, using the bq tool will usually be sufficient, or for more complex use cases, the BigQuery client libraries enable programming with BigQuery from multiple languages. It can still be useful sometimes to make plain requests to the REST APIs to see how certain APIs work at a low level, however.
First, make sure that you have installed the Google Cloud SDK. This should include the gcloud and bq command-line tools. If you haven't already, authorize your account by running this command from your terminal:
gcloud auth login
This should prompt you to log in and then give you an access code that you can paste into your terminal. (The exact process may change over time).
Now let's try a query using the BigQuery REST API, calling the jobs.query method. Modify this script with your own project name, which you can find from the Google Cloud Console, then paste the script into your terminal:
PROJECT="YOUR_PROJECT_NAME"
QUERY="\"SELECT 1 AS x, 'foo' AS y;\""
REQUEST="{\"kind\":\"bigquery#queryRequest\",\"useLegacySql\":false,\"query\":$QUERY}"
echo $REQUEST | \
curl -X POST -d #- -H "Content-Type: application/json" \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
https://www.googleapis.com/bigquery/v2/projects/$PROJECT/queries
If it worked, you should see output that looks like this:
{
"kind": "bigquery#queryResponse",
"schema": {
"fields": [
{
"name": "x",
"type": "INTEGER",
"mode": "NULLABLE"
},
{
"name": "y",
"type": "STRING",
"mode": "NULLABLE"
}
]
},
"jobReference": {
"projectId": "<your project ID>",
"jobId": "<your job ID>"
},
"totalRows": "1",
"rows": [
{
"f": [
{
"v": "1"
},
{
"v": "foo"
}
]
}
],
"totalBytesProcessed": "0",
"jobComplete": true,
"cacheHit": false
}
If you haven't set up the bq command-line tool, you can use bq init from your terminal to do so. Once you have, you can try running the same query using it:
bq query --use_legacy_sql=False "SELECT 1 AS x, 'foo' AS y;"
You can also see the REST API requests that the bq tool makes by passing the --apilog= option:
bq --apilog= query --use_legacy_sql=False "SELECT [1, 2, 3] AS x;"
Now let's try an example using the jobs.insert method instead of the query API. Run this script, replacing YOUR_PROJECT_NAME with your project name:
PROJECT="YOUR_PROJECT_NAME"
QUERY="\"SELECT 1 AS x, 'foo' AS y;\""
REQUEST="{\"configuration\":{\"query\":{\"useLegacySql\":false,\"query\":${QUERY}}}}"
echo $REQUEST | \
curl -X POST -d #- -H "Content-Type: application/json" \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
https://www.googleapis.com/bigquery/v2/projects/$PROJECT/jobs
Unlike the query API, which returned a response immediately, you will see a result that looks similar to this:
{
"kind": "bigquery#job",
"etag": "\"<etag string>\"",
"id": "<project name>:<job ID>",
"selfLink": "https://www.googleapis.com/bigquery/v2/projects/<project name>/jobs/<job ID>",
"jobReference": {
"projectId": "<project name>",
"jobId": "<job ID>"
},
"configuration": {
"query": {
"query": "SELECT 1 AS x, 'foo' AS y;",
"destinationTable": {
"projectId": "<project name>",
"datasetId": "<anonymous dataset>",
"tableId": "<anonymous table>"
},
"createDisposition": "CREATE_IF_NEEDED",
"writeDisposition": "WRITE_TRUNCATE",
"useLegacySql": false
}
},
"status": {
"state": "RUNNING"
},
"statistics": {
"creationTime": "<timestamp millis>",
"startTime": "<timestamp millis>"
},
"user_email": "<your email address>"
}
Notice the status:
"status": {
"state": "RUNNING"
},
If you want to check on the job now, you can use the jobs.get method. Similar to before, run this from your terminal, using the job ID from the output in the previous step:
PROJECT="YOUR_PROJECT_NAME"
JOB_ID="YOUR_JOB_ID"
curl -H "Authorization: Bearer $(gcloud auth print-access-token)" \
https://www.googleapis.com/bigquery/v2/projects/$PROJECT/jobs/$JOB_ID
If the query is done, you'll get a response that indicates as much:
...
"status": {
"state": "DONE"
},
...
Finally, we can make a request to fetch the query results, also using the REST API.
curl -H "Authorization: Bearer $(gcloud auth print-access-token)" \
https://www.googleapis.com/bigquery/v2/projects/$PROJECT/queries/$JOB_ID
The output will look similar to when we used the jobs.query method above:
{
"kind": "bigquery#getQueryResultsResponse",
"etag": "\"<etag string>\"",
"schema": {
"fields": [
{
"name": "x",
"type": "INTEGER",
"mode": "NULLABLE"
},
{
"name": "y",
"type": "STRING",
"mode": "NULLABLE"
}
]
},
"jobReference": {
"projectId": "<project ID>",
"jobId": "<job ID>"
},
"totalRows": "1",
"rows": [
{
"f": [
{
"v": "1"
},
{
"v": "foo"
}
]
}
],
"totalBytesProcessed": "0",
"jobComplete": true,
"cacheHit": true
}

Swagger UI doesn't show embedded json properties model

I am using the swagger tool for documenting my Jersey based REST API (the swaggerui I am using was downloaded on June 2014 don't know if this issue has been fixed in later versions but as I made a lot of customization to its code so I don't have the option to download the latest without investing lot of time to customize it again).
So far and until now, all my transfer objects have one level deep properties (no embedded pojos). But now that I added some rest paths that are returning more complex objects (two levels of depth) I found that SwaggerUI is not expanding the JSON model schema when having embedded objects.
Here is the important part of the swagger doc:
...
{
"path": "/user/combo",
"operations": [{
"method": "POST",
"summary": "Inserts a combo (user, address)",
"notes": "Will insert a new user and a address definition in a single step",
"type": "UserAndAddressWithIdSwaggerDto",
"nickname": "insertCombo",
"consumes": ["application/json"],
"parameters": [{
"name": "body",
"description": "New user and address combo",
"required": true,
"type": "UserAndAddressWithIdSwaggerDto",
"paramType": "body",
"allowMultiple": false
}],
"responseMessages": [{
"code": 200,
"message": "OK",
"responseModel": "UserAndAddressWithIdSwaggerDto"
}]
}]
}
...
"models": {
"UserAndAddressWithIdSwaggerDto": {
"id": "UserAndAddressWithIdSwaggerDto",
"description": "",
"required": ["user",
"address"],
"properties": {
"user": {
"$ref": "UserDto",
"description": "User"
},
"address": {
"$ref": "AddressDto",
"description": "Address"
}
}
},
"UserDto": {
"id": "UserDto",
"properties": {
"userId": {
"type": "integer",
"format": "int64"
},
"name": {
"type": "string"
},...
},
"AddressDto": {
"id": "AddressDto",
"properties": {
"addressId": {
"type": "integer",
"format": "int64"
},
"street": {
"type": "string"
},...
}
}
...
The embedded objects are User and Address, their models are being created correctly as shown in the json response.
But when opening the SwaggerUI I can only see:
{
"user": "UserDto",
"address": "AddressDto"
}
But I should see something like:
{
"user": {
"userId": "integer",
"name": "string",...
},
"address": {
"addressId": "integer",
"street": "string",...
}
}
Something may be wrong in the code that expands the internal properties, the javascript console doesn't show any error so I assume this is a bug.
I found the solution, there is a a line of code that needs to be modified to make it work properly:
In the swagger.js file there is a getSampleValue function with a conditional checking for undefined:
SwaggerModelProperty.prototype.getSampleValue = function(modelsToIgnore) {
var result;
if ((this.refModel != null) && (modelsToIgnore[this.refModel.name] === 'undefined'))
...
I updated the equality check to (removing quotes):
modelsToIgnore[this.refModel.name] === undefined
After that, SwaggerUI is able to show the embedded models.