mongoose $literal in find method projection - database

I have a mongoose find method like this,
photo.find({},{
name:1,
src:1,
likes:{$literal:[]},
dislikes:{$literal:[]},
}).then(photos => ....)
what I want is, when I run the code likes and dislikes field must be an empty array for every record.
I try this way but not working.
Unsupported projection option: likes: { $literal: 1 }
Any idea to add default value for any field in find method ?

As per mongoose, document schema is constructed during its creation. So you can also edit the schema with a default value, so for every record, when it is created it will create likes, and dislikes with empty values.
You can also do this way, if you feel the schema control is not in your hands.
https://mongoosejs.com/docs/2.7.x/docs/defaults.html
photo.find({ 'name' : '1', 'likes': {$ne: []}})

Related

MongoDB: deleting an array value in multiple documents in one collection using pymongo

Afternoon all. I hope you can help with a problem. I am using creating a Flask app and using pymongo and I need to delete a singular array value from multiple arrays across many documents within one collection. I have recipe documents within a 'recipes' collection, and within each of them is an array ('category') that can be between 1 and 3 values in length. I have a feature available within the admin section of my site that allows for the deletion of a category from the 'categories' collection and so, to go with that, I want to delete any instances of that category value within the 'category' array on any recipe document within the recipes 'collection'.
I have managed to do this on a single document:
mongo.db.recipes.update(
{"_id": ObjectId("60df2eec9df14e58d0c698c8")},
{"$pull": {"category": category_id}}
)
but have not managed this on the collection as a whole I have determined I need to use the $all with the $pull operator on the collection using the 'update_many' query and have so far tried:
mongo.db.recipes.update_many({"category": {"$all": {"$pull": {"category": category_id}}}})
mongo.db.recipes.update_many({"$all": {"$pull": {"category": category_id}}})
mongo.db.recipes.update_many({"category": {"$pullAll": {"category": category_id}}})
None of them work. I keep getting a the error:
TypeError: update_many() missing 1 required positional argument: 'update'
Any help would be appreciated.
Read - https://pymongo.readthedocs.io/en/stable/api/pymongo/collection.html?highlight=update_many#pymongo.collection.Collection.update_many
1st parameter is filter which will be {} if you want to update all document
mongo.db.recipes.update_many(
{} // filter filter,
{} // update
)
mongo.db.recipes.update_many({ }, {"$pull": {"category": category_id}})

Mongoose: (CastError) Cast to [ObjectId] failed for value

I'm having a lil problem I've been trying to solve for a while and despite looking online pretty much everywhere I can't find the solution to my problem.
I have 2 mongoose schemas. One "Post" schema and one "Tag" schema.
const postSchema = new Schema({
creator:{type:mongoose.Types.ObjectId, required:true, ref:'User'},
type:{type:String, required:true},
title:{type:String, maxlength:14},
description:{type:String, maxlength:1140},
content:{type:String},
tags:[{type:mongoose.Types.ObjectId, ref:'Tag'}],
date:{type:Date},
});
const tagSchema = new Schema({
name:{type:String, required:true, unique:true},
bgImages:[{type:String}],
posts:[{type:mongoose.Types.ObjectId, ref:'Post'}],
});
When I create a new post, I want to be able to add multiple tags to the tags array in the Post, so what I tried doing is find the ID's of the tags selected by the user and send the array of id's in the POST request.
This is the exact error I get:
'tags.0': CastError: Cast to [ObjectId] failed for value "["60d193ab04caf9336cc9169b,60d193b504caf9336cc9169c"]" (type string) at path "tags.0"
Both the ID's exist in the Tag collection. If I send only one Id in the request it works, but if I send an array of Id's it doesn't.
Something I have in mind is that it sends an array of a single string from what looks like, instead of an array of strings (where each string is the ID).
Can someone help me figure out what's the issue? Thanks a lot.
Found the problem. As I thought it's because I was sending an array containing one single string instead of an array of atomic strings.
Had to split the array with "," to solve the problem.

How can I make a multiple options query with mongodb driver for nodejs?

I'm working in a MongoDB query with Nodejs and I have a problem that I can't resolve.
Let us supposed we have a lot of documents in Mongo and each document have a tags array
tags: [tag1, tag2, tag3]
Front-end are going to send the parameters and we want to make a query with those... How can I find every document inside Mongo with those tags. The tags can be differents, not all documents have the same tags but I want to pull each document that have almost one of those tags. I don't know if I make myself clear with this but I hope you'll help me.
PD: If the query works, we have more than 13 that I can apply so it needs to be something like dynamically query o something.
Regards
This is where the mongodb's aggregate function comes in play
lets say there is a database called books and we want to get books that contain lets say ['fantasy', 'sci-fi'] in its genres
db.book.aggregate([{
$match:{
genres:{
$in:['fantasy', 'sci-fi']
}
}
}])
this will get the result you want, finding all the books that contain either fantasy, or scifi
db.book.aggregate([{
$match:{
genres:{
$all:['fantasy', 'sci-fi']
}
}
}])
This will get all the books that have genres with both fantasy and sf
db.book.aggregate([{
$match:{
genres:{
$nin:['fantasy', 'sci-fi']
}
}
}])
This will fetch all the books that don't have these values
generate an $or condition in your code according to the parameters:
let or_array = [];
params.forEach(params, (tag_param) => {
or_array.push({tags: tag_param})
});
let or_cond = {$or: or_array};
now we just need a simple find query to retrieve the documents:
let results = model.find(or_cond);
results should contain the wanted documents.
** note that $or requires a none empty array so you should validate at least one parameter is received from the client side.

How does one get properties from related table as properties of it's own table in Laravel 5?

The question might sound a little bit confusing but I don't know how to explain it better in one sentence.
This describes basically what the problem is:
I have a Users table which can contain 2 types of users. I know how I can separate by role. But here's the thing, users with role 1(editor_in_chief) have different attributes than users with role 2(reviewer).
My idea was to create a table named 'reviewer_attributes' and 'editor_in_chief_attributes' and create a one-to-one relation with this table to hold the attributes for the users table.
Maybe you have a better idea, that would be great as well. But for this scenario, I would like to know if it is possible to make a call to the database and to get these users' properties from the other table as properties of the User object.
When using a DB call using relations laravel will give me something like this:
user {
id: 1,
name: "Name",
reviewer_attributes: {
attribute_1: 'attribute_1',
attribute_2: 'attribute_2',
attribute_3: 'attribute_3',
}
}
But this is what I want to object to obtain look like:
user {
id: 1,
name: "Name",
attribute_1: 'attribute_1',
attribute_2: 'attribute_2',
attribute_3: 'attribute_3',
}
I want to achieve this by a single database call instead of setting the properties after the call.
I find this a very interesting topic, I hope you could help!
If I got your problem right, you may call somthing like this:
DB::table('users')
->join('reviewer_attributes', 'users.id', '=', 'reviewer_attributes.user_id')
->find($id);
you may add select to get specific attributes of each table:
DB::table('users')
->join('reviewer_attributes', 'users.id', '=', 'reviewer_attributes.user_id')
->select('users.id', 'users.name', 'reviewer_attributes.*')
->find($id);
Update: You can also use collections to restructure your results returned by Eloquent:
$result = User::with('reviewerAttributes')->find($id);
$result = $result->get('reviewer_attributes')
->merge($result->forget('reviewer_attributes')->all())
->all();
You need export model to Json?
If so, override toArray method
public function toArray()
{
$arr = parent::toArray();
$reviewer_attributes = $this->getReviewerAttributesSomeHow();
return array_merge($arr, $reviewer_attributes);
}

MongoDB: Query and retrieve objects inside embedded array?

Let's say I have the following document schema in a collection called 'users':
{
name: 'John',
items: [ {}, {}, {}, ... ]
}
The 'items' array contains objects in the following format:
{
item_id: "1234",
name: "some item"
}
Each user can have multiple items embedded in the 'items' array.
Now, I want to be able to fetch an item by an item_id for a given user.
For example, I want to get the item with id "1234" that belong to the user with name "John".
Can I do this with mongoDB? I'd like to utilize its powerful array indexing, but I'm not sure if you can run queries on embedded arrays and return objects from the array instead of the document that contains it.
I know I can fetch users that have a certain item using {users.items.item_id: "1234"}. But I want to fetch the actual item from the array, not the user.
Alternatively, is there maybe a better way to organize this data so that I can easily get what I want? I'm still fairly new to mongodb.
Thanks for any help or advice you can provide.
The question is old, but the response has changed since the time. With MongoDB >= 2.2, you can do :
db.users.find( { name: "John"}, { items: { $elemMatch: { item_id: "1234" } } })
You will have :
{
name: "John",
items:
[
{
item_id: "1234",
name: "some item"
}
]
}
See Documentation of $elemMatch
There are a couple of things to note about this:
1) I find that the hardest thing for folks learning MongoDB is UN-learning the relational thinking that they're used to. Your data model looks to be the right one.
2) Normally, what you do with MongoDB is return the entire document into the client program, and then search for the portion of the document that you want on the client side using your client programming language.
In your example, you'd fetch the entire 'user' document and then iterate through the 'items[]' array on the client side.
3) If you want to return just the 'items[]' array, you can do so by using the 'Field Selection' syntax. See http://www.mongodb.org/display/DOCS/Querying#Querying-FieldSelection for details. Unfortunately, it will return the entire 'items[]' array, and not just one element of the array.
4) There is an existing Jira ticket to add this functionality: it is https://jira.mongodb.org/browse/SERVER-828 SERVER-828. It looks like it's been added to the latest 2.1 (development) branch: that means it will be available for production use when release 2.2 ships.
If this is an embedded array, then you can't retrieve its elements directly. The retrieved document will have form of a user (root document), although not all fields may be filled (depending on your query).
If you want to retrieve just that element, then you have to store it as a separate document in a separate collection. It will have one additional field, user_id (can be part of _id). Then it's trivial to do what you want.
A sample document might look like this:
{
_id: {user_id: ObjectId, item_id: "1234"},
name: "some item"
}
Note that this structure ensures uniqueness of item_id per user (I'm not sure you want this or not).

Resources