Loopback and MongoDB Embedded Documents Defining JSON Model - mongodb

Can / how do you define an embedded document in a model's json definition with LoopbackJS without creating a model to represent the sub-document?
For example, consider this following MongoDB document:
{
_id: ObjectId("some_mongodb_id"),
subDocs: [
{
"propertyA": "a1",
"propertyB": "b1"
},
{
"propertyA": "a2",
"propertyB": "b2"
}
]
}
I could create two models in loopback:
some-model.json:
...
"properties": {
"subDocs": [
"SubDocsModel"
]
}
sub-docs-model.json:
...
"properties": {
"propertyA": "string",
"propertyB": "string"
}
Rather than doing that, however, I'd like to just declare the sub-doc model inline in the some-model.json since it's just there to document the shape of some-model's document.
Is that possible? Something like:
some-model.json:
...
"properties":{
"subDocs": [
{
"propertyA": {
"type": "string"
},
"propertyB": {
"type": "string"
}
}
]
}
I tried the above, but what I end up with is a field in my mongodb document that's of type string with the value [object Object]...
The purpose would be (1) to document the shape of the sub-document, and (2) to allow for validation by loopback without adding custom logic.

You can define it as an object
some-model.json:
"properties": {
"subDocs": ["object"]
}
But if you want validation or have a structure for sub-docs, you need to create a loopback model for that.
Loopback does not do any validation, ... for properties with type object.

Related

How can I delete or update particular object in an array of object while using mongoose and nestjs

I want to update or delete a particular field (subTags:) in an array of objects.
{
"_id": {
"$oid": "63c175a0ec5dac10b35ac9da"
},
"name": "clerk",
"description": "clerical duties including typing and filing.",
"tags": "assistant receptionist typist ",
"__v": 0,
"subCategory": [
{
"name": "tele-clerk",
"subTags": [
"assistant",
"receptionist"
]
},
{
"name": "administrative-clerk",
"subTags": [
"assistant",
"receptionist",
"typist"
]
}
]
}
I tried using :
const updatedSubCategory = await this.categories.findOneAndUpdate({name:category.name,"subCategory.name": category.subCategory.name},{ $addToSet:{subCategory: category.subCategory}},{new:true})
but it is creating another new object inside subcategory array of same name I don't want that to happen.The name field in the subcategory must be unique.
my schema is :
#Schema({collection:'category'})
export class SubCategorySchema {
#Prop({unique:true})
name:string
#Prop()
tags:string[]
}
#Schema({collection:'category'})
export class CategorySchema {
#Prop({unique:true, lowercase:true})
name:string
#Prop({lowercase:true})
subCategory:SubCategorySchema[]
#Prop({lowercase:true})
description:string
#Prop({lowercase:true})
tags:string
}

How to use nested query using &or with &any in mongodb?

I'm learning mongoDB queries and have a problem given my collection looks like:
"filename": "myfile.png",
"updatedCoordinates": [
{
"xmin": 537.640869140625,
"xmax": 1049.36376953125,
"ymin": 204.90736389160156,
"ymax": 714.813720703125,
"label": "LABEL_0",
"status": "UNCHANGED"
},
{
"xmin": 76.68355560302734,
"xmax": 544.8860473632812,
"ymin": 151.90313720703125,
"ymax": 807.1371459960938,
"label": "LABEL_0",
"status": "UNCHANGED"
}],
"predictedCoordinates": [
{
"xmin": 537.640869140625,
"xmax": 1049.36376953125,
"ymin": 204.90736389160156,
"ymax": 714.813720703125,
"status": "UNCHANGED",
"label": "LABEL_0"
}
]
and the eligible values of status are: UNCHANGED, CHANGED, UNDETECTED
How would I query: Get all the in instances from the db where status == CHANGED / UNDECTED for ANY of the values inside either updatedCoordinates or predictedCoordinates ?
It means that if status of minimum of 1 entry inside either updated or predicted is set to changed or undetected, it's eligible for my query.
I tried:
{"$or":[{"updatedCoordinates.status": "CHANGED"}, {"predictedCoordinates.status": "CHANGED"}]}
With Python dict, I can query as:
def find_eligible(single_instance:dict):
for key in ["predictedCoordinates", "updatedCoordinates"]:
for i in single_instance[key]:
if i["status"] in ["CHANGED", "UNDETECTED]: return True
return False
But retrieving 400K instances first just to filter a few ones is not a good idea.
Try running this query:
db.collection.find({
"$or": [
{
"updatedCoordinates.status": {
"$in": [
"CHANGED",
"UNDETECTED"
]
}
},
{
"predictedCoordinates.status": {
"$in": [
"CHANGED",
"UNDETECTED"
]
}
}
]
})
Mongodb playground link: https://mongoplayground.net/p/Qda-G5L1mbR
Simple use of Mongo's dot notation allows access to nested values in arrays / objects, like so:
db.collection.find({
"updatedCoordinates.status": "CHANGED"
})
Mongo Playground

how to update partial document of an array

i have a person document, that have list of pets:
{
"personId": "kjadfh97r0",
"pets": [
{
"petId": "dfjkh32476",
"name": "kitty",
"kind": "cat"
},
{
"petId": "askdjfh2794857",
"name": "rexy",
"kind": "dog"
}
]
}
I want to find certain pen inside of certain person and update just some fields, so I did something like:
db.people.findAndModify({
query: { "personId": "kjadfh97r0", "pets.petId": "dfjkh32476" },
update: {"$set":{"pets.$":{"kind":"tiger"}}}
})
but what happens to me is that the whole document is replaced with "kind":"tiger", and I just wanted to update the "kind" field any keep the rest.
You should specify entire path for $set when you update nested document using positional operator, otherwise the document will be replaced:
db.people.findAndModify({
query: { "personId": "kjadfh97r0", "pets.petId": "dfjkh32476" },
update: { $set: {"pets.$.kind": "tiger"} }
})

Querying nested mongo document [duplicate]

This question already has answers here:
MongoDB - how to query for a nested item inside a collection?
(3 answers)
Closed 6 years ago.
I have few JSON documents stored in MongoDB that are basically error reports, i.e. each document contains a nested data structure mismatches between datasets. They look like the following:
{
"nodename": "BLAH"
"errors": {
"PC": {
"value": {
"PC93196": [
"post",
"casper"
],
"PC03196": [
"netdb"
]
}
}
}
}
So in the above case, a process/tool determines the PC value of PC93196 and PC03196. netdb in this case reported a different PC value to that of post and casper.
How do I query for all documents that have errors where the process/tool casper is involved?
The document schema doesn't really lend itself to being queried very easily in the way you're trying to. This is because the value object is composed of named objects, rather than being an Array of objects. I.e. the value object has two properties: PC93196 and PC03196.
If your document was structured slightly differently it would be much easier to query in the way you want. For example a document structure like this:
{
"nodename": "BLAH",
"errors": {
"PC": [
{
"name": "PC93196",
"type": [
"post",
"casper"
]
},
{
"name": "PC03196",
"type": [
"netdb"
]
}
]
}
}
Would allow you to write a query like this:
db.errors.aggregate([{$unwind:"$errors.PC"},{$match:{"errors.PC.type":"casper"}}])
which would provide a result:
{ "_id" : ObjectId("5763c480dad14fd061657f91"), "nodename" : "BLAH", "errors" : { "PC" : { "name" : "PC93196", "type" : [ "post", "casper" ] } } }

How to update names field nested in an array in mongodb

I have this object and I'd like to update the name field "field" of all the document in the collections. I read the mongodb documentation and it says $rename doesn't work in this case. I should execute a forEach but I don't know how which command use
{
"name": "foo"
"array": [
"object": {
"field": "name"
}
]
}
Do it manually:
db.collection.find().forEach(function(doc) {
if (doc.array) {
doc.array.forEach(function(edoc) {
if (edoc.object) {
doc.object.new_field = edoc.object.field
delete edoc.object.field
}
})
db.test.update({ "_id" : doc._id }, doc)
}
})
This should get you started. It handles missing or empty array arrays, but not an array value of the wrong type, or an object value of the wrong type.
$rename modifier for update Ops should work (http://docs.mongodb.org/manual/reference/operator/update/rename/)
Imagine a collection like yours:
{
"name": "foo",
"array":[
{"field": "name" }
]
}
You will be able to do something like this:
db.rename.update({},{$rename:{"name":"newName"}});
And the document will be as follows:
{
"newName": "foo",
"array":[
{"field": "name" }
]
}
In order to update all the collection you should use the multi option as follows:
db.rename.update({},{$rename:{"name":"newName"}}, {multi:true})
Regards