Query generated mongo-version collection without model - mongodb

I want to use mongoose-version to track and keep changes in mongodb.
I created this example schema.
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var version = require('mongoose-version');
var PageSchema = new Schema({
title : { type : String, required : true},
tags : [String],
});
PageSchema.plugin(version, { collection: 'Page__versions' });
const PageModel = mongoose.model('PageModel', PageSchema)
So all versions are stored in collection Page__versions, but how can I query this collection, because I don't have a model for that collection.

To get the collection you can use the mongoose database object that is returned from the createConnection function. So when you start the application you store this variable like this
let db = mongoose.createConnection(url, params);
And then you can use this object to get the collection you want, in this case
let collection = db.collection("Page__versions");
At this point you can use the standard methods to do CRUD operations on that collection, for example if you want to find all documents that have a specific property in that collection, you can do something like this
collection.find({myProperty: value});
And this will give you all documents that are in that collection that matches the criteria.
If you don't know the model you can always get one item from the collection and see what the result is
let doc = collection.findOne({}); //This will get the first document in the collection

Related

mongoose - perfroming CRUD operations on a sub document

I'm creating a mern app, and pretty new to mongodb and mongoose, and I'm currently struggling with the concept of the subdocument in mongodb and how to perform crud operations in express. I've been researching and haven't found many tutorials or articles on subdocuments, mostly the referenced documents and population.
I have two separate schemas
var ProjectSchema= new mongoose.Schema({
title:{
type:String,
required:true,
unique:true
},
description:String,
lists: [ListSchema]
})
var ListSchema= new mongoose.Schema({
name: {
type:String,
required:true
}
})
Currently, i'm trying to insert data into the List schema.
listRouter.post('/api/project/:projectId/list/new', asyncMiddleware(async function(req,res,next){
Project.findById(req.params.projectId, await function(err,items){
items.lists.push(req.body)
items.save();
res.json(items)
})
}))
What happens is that the data are inserted into the Project.lists but when I check the List collection in mongodb, it's empty.
From my reading the sub documents documentation , it stats you can't save the sub documents individually, you have to do via the parent document- which I have in the code above.
Doesn't the List collection supposed to automatically get the new data after saving the Project document? Or something else is happening? Any input would be appreciated.

MongoDB: projection on specific fields of all objects in an array

I have a MongoDB database with following data structure for one Part:
Part Data structure
Now I want to to have a projection on the element Descriptionof every object in the array SensorData. Using the MonogDB API in .NET with C# my code would look the following:
var projection = Builders<Part>.Projection
.Include(part => part.SensorData[0].Description)
.Include(part => part.SensorData[1].Description)
.Include(part => part.SensorData[2].Description)
//...
;
The problem is that the number of objects in SensorData is dynamic and may range from 0 to about 20, so including every Descriptionfield for itself is not possible. The projection has to be done Server-Side as SensorData -> Values can be huge.
Is there any Syntax or method to do this kind of projection?
Just found a solution after asking a colleague: It isn't possible to do this with the Projection Builder, but it is with the aggregation framework:
var match = new BsonDocument
{
{
"$project",
new BsonDocument
{
{"PartData.Description", 1 }
}
}
};
var pipeline = new[] { match };
var aggregationCursor = parts.Aggregate<Part>(pipeline);
var query = aggregationCursor
.ToEnumerable()//needed to perform AsQueryable
.AsQueryable()//Asking for data elements
}

Query or command to find a Document, given an ObjectID but NOT a collection

So I have a document that has references to foreign ObjectIDs that may point to other documents or collections.
For example this is the pseudo-structure of the document
{
_id: ObjectID(xxxxxxxx),
....
reference: ObjectID(yyyyyyyy)
}
I can't find anything that does not involve providing the collection and given that I don't know for sure on which collection to search, I am wondering if there is a way for me to find the document in the entire database and find the collection ObjectID(yyyyyyyy) belongs to.
The only possible way to do this is by listing every collection in the database and performing a db.collection.find() on each one.
E.g. in the Mongo shell I would do something like
var result = new Array();
var collections = db.getCollectionNames();
for (var i = 0; i < collections.length; i++) {
var found = db.getCollection(collections[i]).findOne({ "_id" : ObjectId("yyyyyyyy") });
if (found) {
result.push(found);
}
}
print(result);
You need to run your query on all collections in your database.
db.getCollectionNames().forEach(function(collection){
db[collection].find({ $or : [
{ _id : ObjectId("535372b537e6210c53005ee5") },
{ reference : ObjectId("535372b537e6210c53005ee5")}]
}).forEach(printjson);
});

DbRef with Mongoose - mongoose-dbref or populate?

I have the following 2 schemas:
Company Event:
var companyEventSchema = new Schema({
name : String,
description
date : Date,
attendees : [ { type : Schema.ObjectId, ref : 'Member' } ],
]});
And Member
var memberSchema = new Schema({
name : String,
emailAddress: String,
password :String,
created: { type: Date, default: Date.now }
});
Is the way i've ref'd Member from companyEventSchema correct?
I'm trying to do something a long the lines of a dbref.
I saw theres a separate project for that though... mongoose-dbref
However, the mongoose docs say the above provides "dbref like functionality"
Which would be more efficient?
You only need to use an actual DBRef (and mongoose-dbref) for the case where a field can contain ObjectIds that reference documents in potentially more than one collection. A DBRef is a tuple of an ObjectId, a collection name, and an optional database name.
Mongoose ref: fields, however, contain just an ObjectId and it's the Mongoose schema that defines what one collection the ObjectIds reference.
So Mongoose ref: fields are more efficient and should always be used unless you need the multi-collection reference support that DBRef provides.

Finding an Embedded Document by a specific property in Mongoose, Node.js, MongodDB

For this app, I'm using Node.js, MongoDB, Mongoose & Express
So I have a Param Object that contains an array of Pivots, and I want to read certain data from the pivots as outlined below
---in models.js-------------------------
var Pivot = new Schema({
value : String
, destination : String
, counter : Number
});
var Param = new Schema({
title : String
, desc : String
, pivots : [Pivot]
});
------------- in main.js --------------
var Param = db.model('Param');
app.get('/:title/:value', function(req, res){
Param.findOne({"title":req.param('title')}, function(err, record){
console.log(record.pivots);
record.pivots.find({"value":req.param('value')}, function(err, m_pivot){
pivot.counter++;
res.redirect(m_pivot.destination);
});
record.save();
});
});
I know that the code works until console.log(record.pivots), since i got a doc collection with the right pivot documents inside.
However, there does not seem to be a find method to let me match an embedded document by the 'value' property defined in the schema. Is it possible to search through this array of embedded documents using .find() or .findOne() , and if not, is there some easy way to access it through mongoose?
varunsrin,
This should do it
app.get('/:title/:value', function(req, res) {
Param.findOne({'pivots.value': req.param('value'), "title":req.param('title')}},
function(err, record) {
record.pivot.counter++;
res.redirect(m_pivot.destination);
record.save();
});
});
Note the pluralization of the query to match the field name in your schema
You can querying using embedded document properties like this:
{'pivot.value': req.param('value')}}
Update in response to comment:
app.get('/:title/:value', function(req, res) {
Param.findOne({'pivot.value': req.param('value'), "title":req.param('title')}},
function(err, record) {
record.pivot.counter++;
res.redirect(m_pivot.destination);
record.save();
});
});
I solved it temporarily using a simple for loop to parse the object array as follows:
for (var i=0; i <record.pivots.length; i++){
if (record.pivots[i].value == req.param('value')){
res.redirect(record.pivots.destination);
}
}
However, I still think that Mongoose must have a simpler way of interacting with embedded documents - and this loop is somewhat slow, especially when the number of embedded documents grows large.
If anyone has any suggestions for a faster way to search this object array either in js or with a mongoose function, please post below.
the biggest problem with this is that if your req has some fields empty (that should act as wildcard), you will not find anything since mongo tries to match empty params as well, so searching for {"user":"bob", "color":""} is not the same as {"user":"bob", "color":"red"} or {"user":"bob"}. this means that you have to first create a query object and filter out any unused parameters before you pass it in, and if you create a query object, you can no longer do something like "user.name=..." because mongo interperets this as an error since it does not first resolve the object literal into a string.
Any ideas on this problem?
ps. You'd think it would be easy enough to make an object like:
user.name="bob"; user.color:"green"; user.signup.time="12342561"
and then just use user as a query object :/
I think you are looking for the "$in" keyword?
As in:
{a: {$in: [10, "hello"]}}
source: MongoDB Queries CheatSheet