how to store string as an objectId using loopback - node.js

I have a Loopback model of project.json
project.json
"properties" : {
"users": {
"type": [
{
"user_id": "string"
}
]
}
}
array of id stored string format
{
"users" : [
{
"user_id" : "5ae319e8ac5718155ca719d0"
},
{
"user_id" : "5ae31a4d770afb158ef6c048"
}
]}
how to store string as an objectId like this
{
"users" : [
{
"user_id" : ObjectId("5ae319e8ac5718155ca719d0")
},
{
"user_id" : ObjectId("5ae31a4d770afb158ef6c048")
}
]
}

In Loopback 4 the string can be stored as ObjectId as follow:
Define this property in your loopback model file
#property({
type: "string",
mongodb: { dataType: "ObjectId" }
})
mainId?: string;

In Project Model
"relations": {
"user": {
"type": "belongsTo",
"model": "user",
"foreignKey": "id"
}}
In User Model
"relations": {
"projects": {
"type": "hasMany",
"model": "project",
"foreignKey": "project_user_id"
}}
If there is no relations, You can use
const ObjectId = require('mongodb').ObjectId;
var userId=ObjectId("5ae319e8ac5718155ca719d0")
and create into db.
You can check the type using typeof(userId). It will be an object.

You should consider to define it as a relationship, not a list of objects. Then you can define relation like users, or members. I assume that a project has many users, and a user can belong to many projects. Then, you need to define hasAndBelongsToMany relationship:
Project.hasAndBelongsToMany(User);
User.hasAndBelongsToMany(Project);
You can read more about it here.

Related

How to define a default value when creating an index in Elasticsearch

I need to create an index in elasticsearch by assigning a default value for a field. Ex,
In python3,
request_body = {
"settings":{
"number_of_shards":1,
"number_of_replicas":1
},
"mappings":{
"properties":{
"name":{
"type":"keyword"
},
"school":{
"type":"keyword"
},
"pass":{
"type":"keyword"
}
}
}
}
from elasticsearch import Elasticsearch
es = Elasticsearch(['https://....'])
es.indices.create(index="test-index", ignore=400, body= request_body)
in above scenario, the index will be created with those fields. But i need to put a default value to "pass" as True. Can i do that here?
Elastic search is schema-less. It allows any number of fields and any content in fields without any logical constraints.
In a distributed system integrity checking can be expensive so checks like RDBMS are not available in elastic search.
Best way is to do validations at client side.
Another approach is to use ingest
Ingest pipelines let you perform common transformations on your data before indexing. For example, you can use pipelines to remove fields, extract values from text, and enrich your data.
**For testing**
POST _ingest/pipeline/_simulate
{
"pipeline": {
"processors": [
{
"script": {
"lang": "painless",
"source": "if (ctx.pass ===null) { ctx.pass='true' }"
}
}
]
},
"docs": [
{
"_index": "index",
"_type": "type",
"_id": "2",
"_source": {
"name": "a",
"school":"aa"
}
}
]
}
PUT _ingest/pipeline/default-value_pipeline
{
"description": "Set default value",
"processors": [
{
"script": {
"lang": "painless",
"source": "if (ctx.pass ===null) { ctx.pass='true' }"
}
}
]
}
**Indexing document**
POST my-index-000001/_doc?pipeline=default-value_pipeline
{
"name":"sss",
"school":"sss"
}
**Result**
{
"_index" : "my-index-000001",
"_type" : "_doc",
"_id" : "hlQDGXoB5tcHqHDtaEQb",
"_score" : 1.0,
"_source" : {
"school" : "sss",
"pass" : "true",
"name" : "sss"
}
},

How to rename keys of items in an array

I am very new to MongoDB and I need to do a somewhat complex Update operation on my collection.
I have this kind of collection:
[
{
"Id": 1,
"extension": [
{
"keyName": "Name",
"value": "Bob"
},
{
"keyAge": "Age",
"value": 20
}
]
},
{
"Id": 2,
"extension": [
{
"keyName": "Name",
"value": "Sam"
},
{
"key": "Name",
"value": "Sam"
}
]
},
{
"Id": 3,
"extension": [
{
"keyName": "Age",
"value": 25
},
{
"key": "Age",
"value": 25
}
]
},
{
"Id": 4
}
]
I would like to update any items in the extension array of all documents
so that when an item is found with a key property, to rename it keyAge.
Here is the expected result:
[
{
"Id": 1,
"extension": [
{
"keyName": "Name",
"value": "Bob"
},
{
"keyAge": "Age",
"value": 20
}
]
},
{
"Id": 2,
"extension": [
{
"keyName": "Name",
"value": "Sam"
},
{
"keyAge": "Name",
"value": "Sam"
}
]
},
{
"Id": 3,
"extension": [
{
"keyName": "Age",
"value": 25
},
{
"keyAge": "Age",
"value": 25
}
]
},
{
"Id": 4
}
]
I tried to use $rename in a similar way to this question:
MongoDB rename database field within array
but I get the same error $rename source may not be dynamic array
I think this solution might also apply to me, I tried using it but it's not updating anything on my side, so I guess I cannot understand how to apply that answer to me...
https://stackoverflow.com/a/49193743/215553
Thanks for the help!
I tried to use $rename in a similar way to this question: MongoDB rename database field within array but I get the same error $rename source may not be dynamic array
There is a note in $rename:
$rename does not work if these fields are in array elements.
You can try update with aggregation pipeline starting from MongoDB 4.2,
check condition id key field is exists
$map to iterate loop of extension array
$map to iterate loop of array that is converted from extension object to array in key-value format
$cond check condition if k is key then return keyAge otherwise return current
$arrayToObject back to convert key-value array return from above map to object original format
db.collection.update(
{ "extension.key": { $exists: true } },
[{
$set: {
extension: {
$map: {
input: "$extension",
in: {
$arrayToObject: {
$map: {
input: { $objectToArray: "$$this" },
in: {
k: {
$cond: [
{ $eq: ["$$this.k", "key"] }, // check "key" field name
"keyAge", // update new name "keyAge"
"$$this.k"
]
},
v: "$$this.v"
}
}
}
}
}
}
}
}],
{ multi: true }
)
Playground
Question : How to Rename or add new key for existing array object key?
Answer : Inside projection of mongodb query we have map property which will resolve this.
Solution Example :
{
parents: {
$map: {
input: "$parents",
as: "parent",
in: {
caaUserId: "$$parent._id",
email: "$$parent.email",
countryCode: "$$parent.countryCode",
mobile: "$$parent.mobile",
reportType : "single"
}
}
}
}
In this example if we want to rename $parent._id as caaUserId in parents array for each Element.
Then we can use map and define caaUserId like $$parent._id. This whole code will work in mongoose projection of Query.
It should return following :
{
"parents" : [
{
"caaUserId" : "62d17fa164057000149e283f",
"email" : "john.doe#hotmail.com",
"countryCode" : 91,
"mobile": 9876543210,
"reportType":"single",
},
{
"caaUserId" : "6195d50f15ae2b001293c486",
"email" : "akka.ash#hotmail.com",
"countryCode" : 91,
"mobile": 9876543211,
"reportType":"multi",
},
]
}
This is something that works in your case. Might not be the most readable though.
import json
data = json.loads(strdata)
for entry in data:
if 'extension' in entry:
for x in entry['extension']:
for k, v in x.items():
if k == 'key':
x['keyAge'] = x.pop(k)

Loopbackjs Querying related model via rest api

is there any way to query related model's related model like from post \Get:
{"order": "created_at DESC","include":[{"relation": "user"}]
But, in my user model there is a relation hasone with settings model. I want to get that also, while querying from post \Get rest api. I've tried with:
{ "include": { "relation": "user","include": {"relation":"settings"}}}
but no luck.
I've create nested relationship to related to your question.
example : teamRole.json
TeamRole > belongTo > User and Team
"validations": [],
"relations": {
"team": {
"type": "belongsTo",
"model": "Team",
"foreignKey": ""
},
"user": {
"type": "belongsTo",
"model": "User",
"foreignKey": ""
}
}
Retrieve results
app.models.TeamRole.findOne({
where: {
userId: user.id
},
include:[ {
relation: 'team'
},
{
relation: 'user'
} ]
},function(err,team,user){
//retrieve relational data here
});
Try this approach, hope this will helpful.

Swagger-1.2 : How to display n-nested JSON objects in Model Schema

I'm using Swagger 1.2 and having a hard time trying to model JSON nested objects, I'd like the Model Schema to display just like in the Swagger online demo Pet store POST/pet (Example Value). For example, my object is:
{
"parent" : {
"child_1" : {
"child_2a" : "string",
"child_2b" : {
"child_3a" : "string",
"child_3b" : ["string"]
}
}
}
}
As you can see, I have a more than 1 level JSON. In my parameter array, I have something like this:
....
stuff here
.....
api: [
{
"path": "/api/foo/bar",
"operations": [
{
"method": "POST",
"summary": "a job",
"consumes": ["application/json"],
"authorizations": {},
"parameters": [
{
"name": "body",
"required": true,
"type" : "Parent",
"description": "some description",
"paramType": "body"
},
{
"name": "fooz",
"description": "some description",
"required": false,
"type": "string",
"paramType": "query"
}
],
......
........
}
],
"models" : {
"Parent": {
"id": "Parent",
"required": ["parent"],
"properties": {
"parent": {
"$ref": "Child1"
}
}
},
"Child1": {
"id": "Child1",
"required" : ["child_1"],
"properties": {
"child_1": {
"$ref": "Child2"
}
}
},
"Child2" : {
"id" : "Child2",
"required" : ["child_2a", "child_2b"],
"properties" : {
"child_2a" : {
"type" : "string"
},
"child_2b" : {
"$ref" : "Child3"
}
}
},
"Child3" : {
"id" : "Child2",
"required" : ["child_3a", "child_3b"],
"properties" : {
"child_3a" : {
"type" : "string"
},
"child_3b" : {
"type" : "array",
"items": {
"type": "string"
}
}
}
}
But the Model Schema display is :
{
"parent" : "Child1"
}
I probably did something incorrect ? How do I get it to display entire nested object in the Model Schema ? Just like the Swagger demo pet store POST/Pet Example Value
Swagger 1.2 requires the entire model definition to be flat--meaning, you cannot have nested, complex objects, only primitives and references to other complex objects.
As of swagger 2.0, you can now have inline, nested or anonymous objects.
So the short answer is, you cannot model what you are describing in 1.2. If you can, please consider updating your libraries to use swagger 2.0.

How to get a certain element out of an array within collection in MongoDB?

I have the following collection named 'CanvasCollection' in mongoDB and I want to get the image object with an id of "50e6fcc2edcbc10613000022" out of the array within this collection:
{
"_id": ObjectId("50d1f440471ca84e1f000007"),
"image": [{
"_id": ObjectId("50e6fcc2edcbc10613000022"),
"type": "image",
"filename": "50e6fcc2edcbc10613000022.jpg",
"origname": "2811879134_7a57d7c586_m.jpg",
"filepath": "upload/50e6fcc2edcbc10613000022.jpg",
"thumbpath": "upload/50e6fcc2edcbc10613000022_small.jpg",)
}],
"text": [{
"_id": ObjectId("50e6eda0edcbc1061300001b"),
"content": "Type your text here"
}]
}
This doesn't seem to work:
CanvasCollection.find({'_id': new BSON.ObjectID('50d1f440471ca84e1f000007')}, {'image' : {$elemMatch: {'_id': new BSON.ObjectID('50e6fcc2edcbc10613000022')}}})
Any ideas how to get exactly this:
{
"_id": ObjectId("50e6fcc2edcbc10613000022"),
"type": "image",
"filename": "50e6fcc2edcbc10613000022.jpg",
"origname": "2811879134_7a57d7c586_m.jpg",
"filepath": "upload/50e6fcc2edcbc10613000022.jpg",
"thumbpath": "upload/50e6fcc2edcbc10613000022_small.jpg",)
}
If you have MongoDb version 2.2 you can do it like this:
db.CanvasCollection.aggregate({$project: {image:1}},{ $unwind : "$image" },{ $match : {"image._id": ObjectId("50e6fcc2edcbc10613000022")}})
(this is from mongo shell), output would be like this:
{
"result" : [
{
"_id" : ObjectId("50d1f440471ca84e1f000007"),
"image" : {
"_id" : ObjectId("50e6fcc2edcbc10613000022"),
"type": "image",
"filename": "50e6fcc2edcbc10613000022.jpg",
"origname": "2811879134_7a57d7c586_m.jpg",
"filepath": "upload/50e6fcc2edcbc10613000022.jpg",
"thumbpath": "upload/50e6fcc2edcbc10613000022_small.jpg"
}
}
],
"ok" : 1
}
About unwind: http://docs.mongodb.org/manual/reference/aggregation/unwind/.
Similar topic: Retrieve only the queried element in an object array in MongoDB collection..
If you have older MongoDb version I think it's impossible.

Resources