How to add data in nested array in mongoshell - node.js

I have a schema :
{
"id": String,
"username": String,
"password": String,
"email": String,
"firstName": String,
"lastName": String,
"system" : {
"item" : {type: Number},
"update_interval" : { type: Number, max: 99999 },
"reading" : [
{
"id" : { type: Number},
"adc1" : { type: Number, max: 4095 },
"adc2" : { type: Number, max: 4095 },
"pc_datestamp" :Date,
}
]
}
now i want to add values to
"reading" : [
{
"id" : { type: Number},
"adc1" : { type: Number, max: 4095 },
"adc2" : { type: Number, max: 4095 },
"pc_datestamp" :Date,
}
]
but i dont know where I am wrong I have tried to update data from mongoshell but no success till now
> db.users.update( {"email" : "test#test.com", "system.item": 1, }, {"$push": {"system.$.reading": [{"adc1" : "123", "adc2": "1245", "id":"1" }] } })
WriteResult({
"nMatched" : 0,
"nUpserted" : 0,
"nModified" : 0,
"writeError" : {
"code" : 16837,
"errmsg" : "The positional operator did not find the match needed from the query. Unexpanded update: system.$.reading"
}
> db.users.update( {"email" : "test#test.com", "system": {$elemMatch:{ item: 1}} }, {"$push": {"system.$.reading": {"adc1" : "123", "adc2": "1245", "id":"1" } } })
WriteResult({ "nMatched" : 0, "nUpserted" : 0, "nModified" : 0 })
I have set the value of item as one
> db.users.find( {"email" : "test#test.com", "system.item": 1} ).pretty()
{
"_id" : ObjectId("56dd88578ff7fbd714091a4a"),
"lastName" : "test",
"firstName" : "test",
"email" : "test#test.com",
"password" : "$2a$10$wY9wr9oreza4fBX7CfXym.rPZUPrcesigYIfWd0zbM4dDjBy6k3vy",
"username" : "test",
"system" : {
"item" : 1,
"reading" : [ ]
},
"__v" : 0
}
I have followed
Mongodb $push in nested array
and this
Insert data in nested array in mongodb
and many more questions but cannot find whats wrong.

Since the positional $ operator acts as a placeholder for the first element that matches the query document, and the array field must appear as part of the query document, your update
operation does not satisfy these conditions hence it suffers from the error fate you are getting. In your query you are only referencing the "system.item" field which is not an array.
The other option you can do is ditch the positional $ operator in your update and just add the object to the array using $addToset which adds elements to an array only if they do not already exist in the set:
db.users.update(
{
"email": "test#test.com",
"system.item": 1
},
{
"$addToSet": {
"system.reading": {
"adc1" : "123",
"adc2": "1245",
"id":"1"
}
}
}
)

Related

How tree structure with mongodb?

Hello I need to know if it is possible to generate a structure tree so that you understand me I have this model:
const StructureSchema = new Schema({
parent: { type: Schema.ObjectId, ref: 'article' },
child : { type: Schema.ObjectId, ref: 'article' },
quantity: { type: Number, default: 0 },
utilization : { type: String},
increasePrice : { type : Number},
optional : { type : Boolean, default : false}
});
It happens that even there it returns me correct when it is a single level it happens that Child can act as Parent too and I would like to bring that structure too.
I was watching $ graphLookup but I could not implement it as I want some idea how to achieve it?
You seem to be using ObjectId (i.e. other _id) for the parent and child keys. I would recommend simplifying your design to using just parent as follows:
var r =
[
{"_id":0, otherData:"foo2"}
,{"_id":3, parent:0, otherData:"foo1"}
,{"_id":4, parent:0, otherData:"foo2"}
,{"_id":5, parent:0, otherData:"foo2"}
,{"_id":6, parent:0, otherData:"foo3"}
,{"_id":7, parent:6, otherData:"foo3"}
,{"_id":8, parent:6, otherData:"foo3"}
,{"_id":9, parent:8, otherData:"foo3"}
];
In this design a record without a parent is the "root."
Both parent-to-child and child-to-parent lookups are possible.
// Child-to-parent lookup:
db.foo.aggregate([
// Find the child we seek:
{$match: {_id: 9}}
// Now get the parent chain:
,{$graphLookup: {
from: "foo",
connectToField: "_id",
connectFromField: "parent",
startWith: "$parent", // usually value of connectFromField
depthField: "n",
as: "zz"
}}
]);
{
"_id" : 9,
"parent" : 8,
"otherData" : "foo3",
"zz" : [
{
"_id" : 8,
"parent" : 6,
"otherData" : "foo3",
"n" : NumberLong(0)
},
{
"_id" : 0,
"otherData" : "foo2",
"n" : NumberLong(2)
},
{
"_id" : 6,
"parent" : 0,
"otherData" : "foo3",
"n" : NumberLong(1)
}
]
}
// Parent-to-child lookup:
db.foo.aggregate([
// Find the parent we seek:
{$match: {_id: 0}} // just go for the top for fun
// Now get the child chains; there can be >1 child for a parent:
,{$graphLookup: {
from: "foo",
connectToField: "parent",
connectFromField: "_id",
startWith: "$_id", // usually value of connectFromField
depthField: "n",
as: "zz"
}}
]);
{
"_id" : 0,
"otherData" : "foo2",
"zz" : [
{
"_id" : 5,
"parent" : 0,
"otherData" : "foo2",
"n" : NumberLong(0)
},
{
"_id" : 8,
"parent" : 6,
"otherData" : "foo3",
"n" : NumberLong(1)
},
{
"_id" : 6,
"parent" : 0,
"otherData" : "foo3",
"n" : NumberLong(0)
},
{
"_id" : 9,
"parent" : 8,
"otherData" : "foo3",
"n" : NumberLong(2)
},
{
"_id" : 4,
"parent" : 0,
"otherData" : "foo2",
"n" : NumberLong(0)
},
{
"_id" : 3,
"parent" : 0,
"otherData" : "foo1",
"n" : NumberLong(0)
},
{
"_id" : 7,
"parent" : 6,
"otherData" : "foo3",
"n" : NumberLong(1)
}
]
}

I keep getting ($__ is not allowed) error while validating a perfectly valid object

I using Node.js API's, I also use Joi package to validate my entries , but I keep getting error ($__ is not allowed) while the form I submit seems to be perfectly valid.
I have searched a lot but couldn't find any useful solution.
Joi version is use is 14.3.1,
and the node version is 14.3.1
here is the schema :
const schema = Joi.object({
name: Joi.string().min(5).max(50).required(),
price : Joi.object().required().allow(),
description : Joi.string().min(15).max(400).required().allow(),
isFavorate : Joi.boolean().required().allow(),
place: Joi.object().required().allow(),
tags : Joi.array().required().allow(),
isDeliveryAvailable : Joi.boolean().required().allow(),
rating: Joi.number().min(0).required().allow(),
images : Joi.required().allow(),
secondHand : Joi.required().allow()
})
return Joi.validate(item , schema) ;
}
The form data:
{
"name" : "an image",
"price" : {
"IQD" : 1000,
"USD" : 10
},
"place" : {
"name" : "fata rap"
},
"description" : "some item safas dfsa d",
"isFavorate" : true,
"tags": ["some tag 1", "tag 2"],
"isDeliveryAvailable": true,
"rating" : 4,
"comments":["comment 1" , "comment 2"],
"variants": [
{"name": "item one variant one", "price":{
"IQD":1000,
"USD": 1}
},
{"name": "item one variant tow", "price":{
"IQD":2000,
"USD": 2}
},
{"name": "item one variant three", "price":{
"IQD":1000,
"USD": 1}
}
],
"category" : "5d479c60e35db51e3084c007",
"secondHand" : "true"
}
the model :
const Item = mongoose.model('Items',new mongoose.Schema({
name: {
type : String,
required: true,
minlength : 5,
maxlength : 50
},
price : {
type: Object,
IQD: {type : Number, required : true, min : 0},
USD: {type : Number, required : true, min : 0 }
},
description : {
type : String,
minlength : 15,
maxlength : 400,
required : true
},
isFavorate: {
type: Boolean,
default: false,
required : true
},
place : {
name : {
type : Object,
required : true,
}
},
tags : {
type : [String],
required : true,
},
isDeliveryAvailable : {
type : Boolean,
default: true,
required: true
},
rating: {
type: Number,
min : 0,
max : 10,
required : true
},
comments : {
type : [String],
},
images: {
type: [Buffer],
requied : true
},
imageURLArray : [String],
variants: [Object],
category: {
type : mongoose.Schema.Types.ObjectId,
ref: 'Category'
},
subcategory: {
type : mongoose.Schema.Types.ObjectId,
ref: 'Subcategory'
},
secondHand : {
type : Boolean,
required : true,
default : false
}
}));
Any ideas will be appreciated. Thanks
once you validate the schema through mongoose the their is no need to validate through Joi . if you remove Joi validation then error will be gone.
I suppose item = new Item(formData); which makes the item a Mongoose object.
If you do this:
Joi.validate(item._doc, schema);
then "$__" is not allowed error is not observed. This looks a bit hacky, though. If I were you, I'd probably use Mongoose to validate before saving to database and perhaps use Joi just to validate user input.

How to perform a part of text search in mongoose array of objects

I have a schema where I need to perform a search in array of objects. I have tried many ways but it doesn't seems to work. Below is my code.
let productsSchema = new mongooseSchema({
productId: {type: mongooseSchema.Types.ObjectId, ref: 'Product'},
mainAttributes: [{
subCategoryId: {type: mongooseSchema.Types.ObjectId, ref: 'CategorySubCategory'},
attributes: Object
}],
createdAt: Date,
updatedAt: Date
})
productsSchema.index({'mainAttributes': 'text'})
let attributes = mongoose.model('Attributes', productsSchema);
let results = await CategorySubCategory.attributes.find({"$text": {"$search": req.body.searchText}})
Currently below record is saved in mongodb
{
"_id" : ObjectId("5bba1b39ad9387431f9f5fd9"),
"productId" : ObjectId("5bba1b397d90713320c441f8"),
"__v" : 0,
"createdAt" : ISODate("2018-10-07T14:42:01.723Z"),
"mainAttributes" : [
{
"_id" : ObjectId("5bba1b397d90713320c441f9"),
"subCategoryId" : ObjectId("5bba1b397d90713320c441f7"),
"attributes" : {
"title" : {
"text" : "some title",
"type" : "text"
}
"state" : {
"text" : "California",
"type" : "text"
},
"city" : {
"text" : "San Francisco",
"type" : "text"
}
}
},
{
"_id" : ObjectId("5bba1b397d90713320c441fb"),
"subCategoryId" : ObjectId("5bba1b397d90713320c441fa"),
"attributes" : {
"temprature" : {
"degree" : "20C",
"type" : "text"
}
}
}
],
"updatedAt" : ISODate("2018-10-07T14:42:01.723Z")
}
I need to perform a search on the basis of text, e.g. when I give San, it should return me the result, but it returns empty.
I have figured it out what was the problem,
I need to explicitly remove an index, and then added
productsSchema.index({'$**': 'text'}) to make it work

How to update a multiple records in an array with sub dictionary in MongoDB

I am trying to update multiple records in an array with in sub dictionary. If where ever that record is found in a collection that record must be update.
My mongoose schema like this:
comments: [{
text: {
type: String,
},
author: {
id: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
name: {
type:String
},
photo:{
type:String
}
}
}]
**My data like this:**
comments : [
{
"text" : "Good one",
"_id" : ObjectId("5722101611a53cca08544d25"),
"author" : {
"id" : "123",
"name" : null,
"photo" : null
}
},
{
"text" : "nice one",
"_id" : ObjectId("5722103511a53cca08544d24"),
"created" : ISODate("2016-04-28T13:29:25.444Z"),
"author" : {
"id" : "123",
"name" :null,
"photo":null
}
},
{
"text" : "Good one",
"_id" : ObjectId("5718768d98eb065c035b645"),
"author" : {
"id" : "456"
}
}]
I want to update name and photo in the the comments array based on the author.id. In the above data to update author.id=123
My code is:
Event.find({'comments.author.id':_id},(err,event)=>{
_.each(event,function(eventData){
_.each(eventData.comments,function(commentData){
if(commentData.author.id ==_id){
console.log("event:"+eventData._id)
Event.update({_id:eventData._id},{$set:{'comments':[{'author.name':username,'author.photo':photoUrl}]}},{multi:true},(err,updateComment)=>{
console.log("commentupdate:"+JSON.stringify(updateComment))
});
}
})
})
})
I am stuck here from last two days.Please give me any solution.Don't make it as duplicate, If it is duplicate please provide a valid answer. Thanks

mongoose text search not returning results

I am trying to create a simple text search on a combined index.
Here is my mongoose model:
// models/user.js
// load the things we need
var mongoose = require('mongoose');
// define the schema for our user model
var itemSchema = mongoose.Schema({
globalinfo : {
ownerobjectid : String,
name : String,
desc : String,
startdate : Date,
enddate : Date,
price : Number,
status : String,
statuscss : String,
dateadded : Date,
locationline1 : String,
locationline2 : String,
locationline3 : String,
locationtown : String,
locationpostcode : String,
locationlatitude : Number,
locationlongitude : Number,
termsapprove : Boolean,
friendlyurl : String,
itemsearchinfo : String,
}
});
itemSchema.index(
{
"globalinfo.itemsearchinfo": "text",
"globalinfo.name": "text"
}
); // schema level
// create the model for users and expose it to our app
module.exports = mongoose.model('Item', itemSchema);
This is my search query:
Item.find(
{ $text : { $search : "item" } }
).exec(function(err, items) {
The issue is that the query always returns no results!
I have one document in the model:
{
"_id" : ObjectId("56781cb97ae92ff08b55d4f1"),
"globalinfo" : {
"friendlyurl" : "item-a",
"dateadded" : ISODate("2015-12-21T15:37:29.591Z"),
"itemsearchinfo" : "Woop lawn mower for rent!\nYou should use this space to describe the item in detail and make it appealing\nTo the renter write your stuff here.",
"statuscss" : "na",
"status" : "Not Available Yet",
"locationlongitude" : null,
"locationlatitude" : null,
"locationpostcode" : "test",
"locationtown" : "test",
"locationline3" : "",
"locationline2" : "",
"locationline1" : "test",
"termsapprove" : true,
"price" : 3,
"enddate" : ISODate("2015-12-31T00:00:00.000Z"),
"startdate" : ISODate("2015-12-23T00:00:00.000Z"),
"desc" : "\n <h3>woop Lawn Mower for Rent! </h3>\n <p>You should use this space to describe the item in detail and make it appealing to the renter <strong>Write your stuff here.</strong> \n </p>",
"name" : "item A",
"ownerobjectid" : "56781909155232b7871edb17"
},
"__v" : 0
}
The output of db.items.getIndexes():
[
{
"v" : 1,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "whatplot_local_db.items"
},
{
"v" : 1,
"key" : {
"_fts" : "text",
"_ftsx" : 1
},
"name" : "itemsearchinfo_text_name_text",
"ns" : "whatplot_local_db.items",
"background" : true,
"weights" : {
"itemsearchinfo" : 1,
"name" : 1
},
"default_language" : "english",
"language_override" : "language",
"textIndexVersion" : 2
}
]
Have you tried re-indexing the collection?
Mongo command:
db.collection.reIndex();
The issue was with the way I was indexing. Using double quotes does not work:
itemSchema.index(
{
"globalinfo.itemsearchinfo": "text",
"globalinfo.name": "text"
}
); // schema level
However single quotes does:
itemSchema.index(
{
'globalinfo.itemsearchinfo': "text",
'globalinfo.name': "text"
}
); // schema level

Resources