Why I can't get document via mongoose? - mongodb

I'm getting document via MongoDB Shell:
db.page_about_love.find()
But I can't get document via mongoose. What is wrong?
mongoose.connect(db_uri);
var loveSchema = new mongoose.Schema({
title: String,
content: String,
tag: String
});
mongoose.model('page_about_love', loveSchema);
var about = mongoose.model('page_about_love');
about.find(function (err, love) {
if (err) return console.error(err);
console.log(love);
});
Test output:
[]

To prevent Mongoose generating a collection name to use, you should be explicit and pass which collection name it should use:
var loveSchema = new mongoose.Schema({
title: String,
content: String,
tag: String
}, { collection : 'page_about_love' });
Otherwise, Mongoose will apply the utils.toCollectionName() function to the model name to determine the collection name, which in your case would yield page_about_loves (notice the pluralization).
More information here.

Related

TypeError: parent.child.push is not a function - issue pushing my object to database

Problem
I'm trying to send data from my client-side form into my database and am running into the error below:
TypeError: artist.fans.push is not a function
The data is an email address that should be saved into my artist model as a subdoc (in an object).
What I've tried
I'm using the syntax from the mongo docs that says parent.children.push() is the proper way to add subdocs to arrays and parent.children.create() to create new subdocuments. Both yield the same error.
Here's my function:
module.exports.addFanEmail = async (req, res) => {
const fan = req.body;
const artist = await Artist.findById(req.params.id);
artist.fans.create(fan);
await artist.save();
res.redirect(`/artists/${artist._id}`);
}
Right now req.body is only the "fan's" email - here's an example of the object's format: { email: 'tom#test.com' }
DB Model
const artistSchema = new Schema({
image: [ImageSchema],
genre: [ String ],
fans: {
email: String,
subscribed: String,
gender: String,
age: Number
},
});
The object is coming through from the client to the function without any problem, I just can't get it to save to the db?

How to find string in array using Mongoose?

I have a schema through mongoose:
const mongoose = require('mongoose');
const recipeSchema = mongoose.Schema({
title: String,
chef: String,
updated: {type: Date, default: Date.now},
region: String,
ingredients: [String],
instructions: [String]
}, { collection: 'recipes' })
module.exports = mongoose.model('Recipes', recipeSchema);
I find the mongoose docs really difficult to understand. I am trying to search for a match of all substring within the 'ingredients' array. I read somewhere that it could be done like so:
.find({ingredients: 'ing1'}) // not working
.find({'ing1': {$in: ingredients}}) // not working
I find it pretty difficult to find in depth tutorials on mongoose as well. Im thinking about not using it at all anymore and just sticking to mongodb shell.
You can use a regex search to match substrings:
.find({ingredients: /ing1/})
The reason that you use mongoose is for testability.
Instead of having to work with a MongoDb instance, which, in Windows can be a pain with the .lock file and the service, mongoose creates the schema that you can test your code with.
The mongoose way is ideal for TDD/TFD.
Below is the model and the mocha test:
recipemodel.js
var mongoose = require('mongoose'),Schema=mongoose.Schema;
var RecipeSchema = new mongoose.Schema({});
RecipeSchema.statics.create = function (params, callback) {
'\\ params is any schema that you pass from the test below
var recipe = new RecipeSchema(params);
recipe.save(function(err, result) {
callback(err, result);
});
return recipe;
};
var recipemodel=mongoose.model('Model', RecipeSchema);
module.exports = recipemodel;
You don't need to describe the schema, mongoose will create it for you when you pass the values of the collection from a mocha test, for example!
The mocha test is below:
var mongooseMock = require('mongoose-mock'),
proxyquire = require('proxyquire'),
chai = require('chai'),
expect = chai.expect,
sinon = require('sinon'),
sinonChai = require("sinon-chai");
chai.use(sinonChai);
describe('Mocksaving a recipe ingredient', function () {
var Recipe;
beforeEach(function () {
Recipe = proxyquire('./recipemodel', {'mongoose': mongooseMock});
});
it('checks if ingredient '+'ing1' + ' saved to mongoose schema', function
(done) {
var callback = sinon.spy();
var recipe = Recipe.create({ title: "faasos", chef:
'faasos',region:'Chennai',ingredients:'ing1',instructions:'abc' },
callback);
expect(recipe.save).calledOnce;
expect(recipe.ingredients).equals('ing341');
done();
});
});
The call to a sinon spy is simply to ensure that the call to the data in the schema got saved (mock saved!) and that the 'save' method did get called at least once. This logic flow is in sync with your actual logic, as you would use in code, when the save on a mongodb collection would be made.
Simply change the value to 'ing1' to make the test pass when you run the test.
For an array type, pass the values as below:
var recipe = Recipe.create({ title: "faasos", chef:
'faasos',region:'Chennai',ingredients:'ing341,ing1',instructions:'abc' }, callback);
expect(recipe.save).calledOnce;
expect(recipe.ingredients).to.include('ing1');
Try this:
.ingredients.find((i) => i === "ing1")
for all elements in the ingredients array, it looks if the content, here a string element, is strictly equal to "ing1"

Correctly inserting and/or updating many datasets to MongoDB (using mongoose)?

So from time to time I get new exports of a cities database of POIs and info about them and I want to have all that data in my MongoDB with a Loopback-API on it. Therefore I reduce the data to my desired structure and try to import it.
For the first time I receive such an export, I can simply insert the data with insertMany().
When I get a new export, it means that it includes updated POIs which I actually want my existing POIs to be replaced with that new data. So I thought I'd use updateMany() but I could'nt figure out how I'd do that in my case.
Here's what I have so far:
const fs = require('fs');
const mongoose = require('mongoose');
const data = JSON.parse(fs.readFileSync('data.json', 'utf8'));
// Connect to database
mongoose.connect('mongodb://localhost/test', {
useMongoClient: true
}, (err) => {
if (err) console.log('Error', err);
});
// Define schema
let poiSchema = new mongoose.Schema({
_id: Number,
name: String,
geo: String,
street: String,
housenumber: String,
phone: String,
website: String,
email: String,
category: String
});
// Set model
let poi = mongoose.model('poi', poiSchema);
// Generate specified data from given export
let reducedData = data['ogr:FeatureCollection']['gml:featureMember'].reduce((endData, iteratedItem) => {
endData = endData.length > 0 ? endData : [];
endData.push({
_id: iteratedItem['service']['fieldX'],
name: iteratedItem['service']['fieldX'],
geo: iteratedItem['service']['fieldX']['fieldY']['fieldZ'],
street: iteratedItem['service']['fieldX'],
housenumber: iteratedItem['service']['fieldX'],
phone: iteratedItem['service']['fieldX'],
website: iteratedItem['service']['fieldX'],
email: iteratedItem['service']['fieldX'],
category: iteratedItem['service']['fieldX']
});
return endData;
}, []);
//
// HERE: ?!?!? Insert/update reduced data in MongoDB collection ?!?!?
//
mongoose.disconnect();
So I just want to update everything that has changed.
Of course if I leave it to insertMany() it fails due to dup key.
For the second time, use mongo's update command with upsert set to true.
db.collection.update(query, update, options)
In the query pass the _id ,in update pass the object and in option set upsert to true. This will update the document if it exists creates a new document if that doesn't exist.

How to query on Embedded document within an array - MongoDB?

I've trying to query on an embedded document i've created that has the following model: a user has a facebook account and a business (emprendimiento). The 'emprendimiento' has categorias_asociadas, that is an empty array that will receive its value(s) from a form tag (Buy, Sell or Invest).
I would like to query all Users that have an emprendimiento that have a catogorias_asociadas that is either buy, sell or invest.**
I'm looking for something like this:
Users.find({'emprendimiento.categorias_asociadas': {$all: 'Buy'}})
var userSchema = mongoose.Schema({
facebook: {
id: String,
token: String,
email: String,
name: String,
photo: String
},
emprendimiento: {
nombre:String,
slogan:String,
logo:String,
web:String,
categorias_asociadas: [],
about: String,
quevende: String,
ubicacion: String,
descripcion: String
}
});
I've accomplished something similar before when I had the 'emprendimiento' in another model:
var emprendimientoSchema= new mongoose.Schema({
nombre:String,
slogan:String,
logo:String,
categorias_asociadas: []
});
var Emprendimiento = mongoose.model('Emprendimiento', emprendimientoSchema)
By doing this query I was able to filter all emprendimiento that have compraVenta (Buy) in its categorias_asociadas.
Emprendimiento.find({categorias_asociadas:{$all:["buy"]}}, function (err, compraventa) {
if (err) {
console.log(err)
}
else {
do something here
}
});
Thanks in advance :)
This worked well :)
Users.find({'emprendimiento.categorias_asociadas': {$all: ['Buy']}})

Is it possible to extract only embedded documents from a Model in Mongoose?

I'd like to run a query on a Model, but only return embedded documents where the query matches. Consider the following...
var EventSchema = new mongoose.Schema({
typ : { type: String },
meta : { type: String }
});
var DaySchema = new mongoose.Schema({
uid: mongoose.Schema.ObjectId,
events: [EventSchema],
dateR: { type: Date, 'default': Date.now }
});
function getem() {
DayModel.find({events.typ : 'magic'}, function(err, days) {
// magic. ideally this would return a list of events rather then days
});
}
That find operation will return a list of DayModel documents. But what I'd really like is a list of EventSchemas alone. Is this possible?
It's not possible to fetch the Event objects directly, but you can restrict which fields your query returns like this:
DayModel.find({events.typ : 'magic'}, ['events'], function(err, days) {
...
});
You will still need to loop through the results to extract the actual embedded fields from the documents returned by the query, however.