mongoose find object into array of object - node.js

I'm new in mongoose and I'm trying to find user by code [user.test.test1.code] , any idea ?
Model :
const userSechema = new mongoose.Schema({
name: {
type: String,
required: true
},
test: [{}],
})
Data :
{
"_id": {
"$oid": "600020ab34742c2d34ae45e5"
},
"test": [{
"test1": {
"code": 11111
},
"test2": {
"code": 22222
}
}]
"name": "daniel"
}
query :
let regex = new RegExp(req.query.searchUserKey, 'i')
const users = await User.find({ $or: [{'name': regex },{'test.test1': { code : regex} }]})
-- Solution --
Thanks you guys, both answers is work for me

Is as simple as do "test.test1.code": 418816 into find query like this:
db.collection.find({
"test.test1.code": 418816
})
This query will give you all documents where exists test.test1.code with value 418816.
Note that this query return the whole document, not only the sub-document into the array. But I'm assuming by your post that a user is the document where exists the field name.
Example here

you can use $elemMatch, check the documentation
const users = await User.find(
{ test: { $elemMatch: { "test1.code": 418816 } } }
)

Related

It is possible to ignore fields if it doesn't exists in document?

I have a model:
const schema = new Schema({
// ....
conditions: {},
// ....
});
Conditions - nested document and I can save anything into it with any key. And let's say we have such conditions:
{
"conditions": {
"age": 10,
"name": "John"
}
}
This is located on the base. Now, I want to find this document, but since I don't know what fields are there, I am facing problems...
const conditions = {
'conditions.age': 10,
'conditions.name': 'John',
'conditions.surname': 'White' // surname doesn't exists
}
const result = await Model.find(conditions);
console.log(result) // [];
And the question is, is it possible to exclude from the filter the fields that are missing in the document? So that find() simply skipped them, did not take them into account...
Use Logical Query Operators $and and $or as below-
const conditions = {
$and: [
{ 'conditions.age': 10, },
{ 'conditions.name': 'John', },
{ $or: [{ 'conditions.surname': { $exists: false } }, { 'conditions.surname': 'White' }] }
]
}
const result = await Model.find(conditions);

how to get specified info from a collection

i have this schema
const todoSchema = new mongoose.Schema({
name: String,
details: String
})
const userSchema = new mongoose.Schema({
name: String,
todo: [todoSchema]
})
i want a rout that gets a specified todo (based on name) for a specified user
this code
await User.findOne({ 'todo._id': req.body.todo_id, _id: req.body.id })
its get all the information of the user not a Single ToDo
such as if i got this
"user": {
"todo": [
{
"_id": "60fc3bd454b38c19a0afd09a",
"name": "hi",
"details": "hello"
} , {
"_id": "60fc3bd454b38c19a0afd09b",
"name": "bye",
"details": "goodbye"
}
]
}
how can i get the todo[1] details
how should i fix it
$ positional operator is what you want.
await User.findOne(
{ 'todo._id': req.body.todo_id,
_id: req.body.id },{
'todo.$': 1 }
})

Mongoose full text search not filtering correctly

So basically i have model with a bunch of string fields like so:
const Schema: Schema = new Schema(
{
title: {
type: String,
trim: true
},
description: {
type: String,
trim: true
},
...
}
);
Schema.index({ '$**': 'text' });
export default mongoose.model('Watch', Schema);
where I index all of them.
Now when I search being that this schema is used as a ref for another model I do a search like this where user is an instance of the other model
const { search, limit = 5 } = req.query;
const query = search && { match: { $text: { $search: new RegExp(search, 'i') } } };
const { schemaRes } = await user
.populate({
path: 'schema',
...query,
options: {
limit
}
})
.execPopulate();
and the searching itself seems to work ok, the problem is when search fields starts to be more specific it seems to me the it does not regard it well.
Example
db
{ title: 'Rolex', name: 'Submariner', description: 'Nice' }
{ title: 'Rolex', name: 'Air-King', description: 'Nice' }
When the search param is Rolex I get both items which is ok but when the search param becomes Rolex Air-King i keep on getting both items which to me is not ok because I would rather get only one.
Is there something I could do to achieve this?
Returning both items is correct, since both items match your search params, but with different similarity score.
You can output the similarity score to help sorting the result.
user.aggregate([
{ $match: { $text: { $search: "Rolex Air-King" } } },
{ $set: { score: { $meta: "textScore" } } }
])
// new RegExp("Rolex Air-King", 'i') is not necessary and even invalid,
// as $search accepts string and is already case-insensitive by default
The query will return
[{
"_id": "...",
"title": "Rolex",
"name": "Air-King",
"description": "Nice",
"score": 2.6
},
{
"_id": "....",
"title": "Rolex",
"name": "Submariner",
"description": "Nice",
"score": 1.1
}]
Since the second result item matches your search query (even partially), MongoDB returns it.
You could use the score to help sort the items. But determining the right threshold to filter the result is complex, as the score depends on the word count as well.
On a side note: You can assign different weights to the fields if they are not equally important
https://docs.mongodb.com/manual/tutorial/control-results-of-text-search/

Can't push items in mongo array

I can't push items into MongoDB array every time that i try to push a new element it creates an empty object and i cant figure out why,
I already used the
Collection.Array.push({element})&
Collection.save()
but i cant figure out a solution
This is My Schema
const Schema = mongoose.Schema;
var ParticipantSchema = new Schema({
nom:{Type:String},
prenom:{Type:String},
email:{Type:String}
})
var CompetitionSchema = new Schema({
nom:String,
date:Date,
place:String,
participant :[ParticipantSchema]
})
module.exports = mongoose.model("Competition",CompetitionSchema);
This is my funtion
exports.addParticipant=function(req,res){
var newParticipant={
"nom":req.body.nom,
"prenom":req.body.prenom,
"email":req.body.email
}
Competition.updateOne(
{ _id:req.body.id},
{ $push: { participant: newParticipant } },
(err,done)=>{
return res.json(done)
}
);
}
the result is always an empty object like below
{
"_id": "5ded0eeb85daa100dc5e57bf",
"nom": "Final",
"date": "2019-01-01T23:00:00.000Z",
"place": "Sousse",
"participant": [
{
"_id": "5ded0eeb85daa100dc5e57c0"
},
{
"_id": "5dee3c1b08474e27ac70672e"
}
],
"__v": 0
}
There is no problem in your code, the only problem is that in schema definition you have Type, but it must be type.
If you update your ParticipantSchema like this, it will work:
var ParticipantSchema = new Schema({
nom: { type: String },
prenom: { type: String },
email: { type: String }
});
You are using another Schema in the Array. This results in so-called subdocuments (https://mongoosejs.com/docs/subdocs.html). Mongoose does not populate subdocuments by default. So all you see is just the _id. You can use the populate method to see all subdocuments in detail. ( https://mongoosejs.com/docs/populate.html ) .
Example :
Competition.
find({}).
populate('participant').
exec(function (err, comps) {
//
});
You can either use populate on the Model or on the Document. For populating a document, take a look at https://mongoosejs.com/docs/api.html#document_Document-populate . There is also a auto-populate plugin available via npm but in most cases it's not necessary : https://www.npmjs.com/package/mongoose-autopopulate .

Find documents by populate match result in mongoose

For Ecample, From this data with mongoose :
Data Students :
[{
"_id": ObjectId("5afbb519a7fe344ff8db67e6"),
"name":"Jack",
"age":20
...
},{
"_id": ObjectId("5afbb534a7fe344gf7db64e7"),
"name":"Joni",
"age":20
...
}]
Data Activities :
[{
"_id": ObjectId("5afbb554a7fe344ff8db67e9"),
"name":"Going to Market",
"student": ObjectId("5afbb519a7fe344ff8db67e6")
...
},{
"_id": ObjectId("5afbb784a7fe344gf7db64e2"),
"name":"Playing with Friends",
"student":ObjectId("5afbb534a7fe344gf7db64e7")
...
}]
I want to find a data base on conditions in populate with regex & This is what i am did :
let term = new Regex('Jack','i');
let result = await Activities.find({})
.populate('student', null, { name: { $regex: term } })
.exec();
But the result is always return all data of Activites (The regex query doesn't work)
What Should I Do?
You should try with using match
let result = await Activities.find({})
.populate({ path: 'student', match: { name: { $regex: term } } })
.exec();

Resources