How can I select single column from MongoDB? - mongodb

I have a users table of the following schema
var usersSchema = mongoose.Schema({
uname : {type : String , unique: true},
email : {type : String},
logintype : {type : String},
password : String,
status : String,
hash : String,
social: {},
games: Object,
os: String,
friends: Object,
msges:Object
});
I want to fetch msges of specific user. I have the username. Currently this is what I am doing
var getMessages = function(user){
global.users.find({"uname" : uname},
{"friends.friendUname":1,_id:0},
function(err,doc){
if(err){
callback(false,err,"",null);
}else{
callback(true,null,"",doc);
}
}
);
}
But I don't want all the fields. Any help?

it should be something like this
global.users.find({"uname" : uname}, 'msges -_id', function (err, doc) {
...
})

Related

Mongoose find is returning a blank array, RoboMongo finds data

I've got an Express application which until this morning was returning an array of objects from the database. Now it's returning an empty array. RoboMongo shows me that the data is still there and doing fine. Any ideas?
My model:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const plotStatusSchema = new Schema(
{
recordDate: Date,
blockName: String,
growerName: String,
company: String,
variety: String,
planted: Number,
region: String,
yieldInKG: Number,
changeInPcnt: Number,
currentRipeness: String,
nextStage: String,
timeToNextInDays: Number,
status: Number
},
{ bufferCommands: false },
{ collection: 'plotStatuses' }
);
const ModelClass = mongoose.model(
'plotStatus',
plotStatusSchema,
'plotStatuses'
);
module.exports = ModelClass;
My returning controller:
const PlotStatus = require('../models/plotStatus');
const jsonpack = require('jsonpack');
exports.plotStatuses = async (req, res) => {
const plotStatus = await PlotStatus.find({
company: 'req.user.companyCode'
}).lean();
if (!plotStatus) {
throw new Error('Plot Statuses not found');
} else {
res.send(plotStatus);
}
};
A sample of my data:
{
"_id" : ObjectId,
"recordDate" : ISODate,
"blockName" : String,
"blockCode" : String,
"growerName" : String,
"company" : String,
"variety" : String,
"planted" : ISODate,
"region" : String,
"yieldInKG" : Number,
"changeInPcnt" : Number,
"currentRipeness" : String,
"nextStage" :String,
"timeToNextInDays" : Number,
"status" : Number,
"targetYieldInKG" : Number,
"currentStatePercentage" : Number,
"totalLengthOfPhase" : Number,
"nextPhaseStart" : ISODate,
"currentBrix" : Number,
"currentPh" : Number,
"currentTA" : Number,
"plotGeoJSON" : Object,
"historicalData" : Array
}
I know that the Schema no longer matches the shape of the JSON, but can I return all the JSONs that fit the find condition anyway?
You are searching the string "req.user.companyCode" inside the company attribute. Obviously, you don't have that company code in your data. Try it again without the quores:
const plotStatus = await PlotStatus.find({
company: req.user.companyCode
}).lean();

[mongodb]How to save a document and automatically increase a field of it?

I need to save or insert a new record into my mongo database. I hope the field "userid" of it can automatically increase by 1. Is it possible to do it in mongodb?
Schema
generalUserApplication: {
userid: Number, // 1
lora: [
{},
{}
]
}
Here's the way from the mongo tutorial.
You need to create new collection counters in your db.
function getNextSequence(db, name, callback) {
db.collection("counters").findAndModify( { _id: name }, null, { $inc: { seq: 1 } }, function(err, result){
if(err) callback(err, result);
callback(err, result.value.seq);
} );
}
Then, you can use getNextSequence() as following, when you insert a new row.
getNextSequence(db, "user_id", function(err, result){
if(!err){
db.collection('users').insert({
"_id": result,
// ...
});
}
});
I have use another package named 'mongoose-sequence-plugin' to generate sequence which is auto-incremented by 1.
Here I am posting code that I have tried for same problem. Hope it will help.
Schema :
var mongoose = require('mongoose');
var sequenceGenerator = require('mongoose-sequence-plugin');
var Schema = mongoose.Schema;
var ProjectSchema = new Schema({
Name : { type : String, required: true },
Description : { type : String, required: true },
DetailAddress : { type : String, required: true },
ShortAddress : { type : String, required: true },
Latitude : { type : Number, required: true },
Longitude : { type : Number, required: true },
PriceMin : { type : Number, required: true, index : true },
PriceMax : { type : Number, required: true, index: true },
Area : { type : Number, required: true },
City : { type : String, required: true }
});
ProjectSchema.plugin(sequenceGenerator, {
field: 'project_id',
startAt: '10000001',
prefix: 'PROJ',
maxSaveRetries: 2
});
module.exports = mongoose.model('Project', ProjectSchema);
This will create projects collection with parameter project_id starting from PROJ10000001 and on wards. If you delete last inserted record then this package reads the current last entry of field project_id and next id is assigned by incrementing current id.

mongoose Schema.index() not working

Using "mongoose": "4.13.6"
Im trying to do a full word search for firstName.
I have Schema
import mongoose from 'mongoose';
let fbUserSchema = mongoose.Schema({
_id : mongoose.Schema.Types.ObjectId,
facebookId : { type: String, required: true, index: true},
gender : String,
profileUrl : String,
imageUrl : String,
firstName : String,
token : String,
email : String
});
fbUserSchema.index({firstName: 'text'});
const fbUser = module.exports = mongoose.model('fbUser', fbUserSchema);
I do a query
import fbUser from '../model/fbUser';
fbUser.find({ $text: { $search: 'Ann' } }, function(err, data) {
if(err) throw err;
console.log(data);
});
This returns me
[]
But in my collection, I have a firstName as 'Anna' .
{
"_id" : ObjectId("5a26d554677475818a795f75"),
"facebookId" : "123456",
"gender" : "Female",
"profileUrl" : "https://www.facebook.com/asdfasf",
"imageUrl" : "/img/profile/sm1.jpg",
"firstName" : "Anna",
"token" : "ldhajksdkjasdakjsdajksd",
"email" : "sm1#gmail.com"
}
Mongoose text search does indeed search for the whole word. If you are trying to get a partial match of a string, you should use $regex instead:
fbUser.find({
firstName: {
$regex: ""^.*Ann.*$"",
$options: "i"
}
}, function(err, data) {
if(err) throw err;
console.log(data);
});

How can I add a unique auto increment ID inside mongoDB object

I have a table users. This is the schema.
var usersSchema = mongoose.Schema({
uname : {type : String , unique: true},
email : {type : String},
logintype : {type : String},
password : String,
status : String,
hash : String,
social: {},
games: Object,
os: String,
friends: Object,
msges:Object
});
The msges are objects. But what I want is to have key value pair inside msges. So what I did was
function sendMsgToFriend(uname,friendUname,title,msg,time,callback){
global.users.find({"uname":friendUname},
function(err,doc){
if(err){
callback(false,err,"Msg cannot be sent");
}else{
global.users.update( {"uname" : uname},
{
$addToSet : {
"msges":{time:{"from":uname,"title":title,"msg":msg,"read":false}}
}
},function(err,doc){
if(err){
callback(false,err,"Msg cannot be sent");
}else{
callback(true,null,"Msg has been sent");
}
}
);
}
}
);
}
I tried to make 'time' the key and rest its value. But what happened was that instead of value of time, string "time" appeared. Can I make an auto increment Key of msges? Thankyou in advance.
You define "msgs" as a object but what i read from your question is you want a array of objects..
Why don't you create a model for messages and make make "msgs" an array of references to that object.
var usersSchema = mongoose.Schema({
uname : {type : String , unique: true},
email : {type : String},
logintype : {type : String},
password : String,
status : String,
hash : String,
social: {},
games: Object,
os: String,
friends: Object,
msges: [{
message_id : { type: Schema.Types.ObjectId, ref: 'Message' },
read_on : Boolean }]
});
and a schema for the messages
var messageSchema = Schema({
from : String,
title: String,
msg : String,
send_on : Date
});
var Message = mongoose.model('Message', messageSchema);
This way all messages are in a collection and you can track the read status per user.
For retrieving the messages during user retriaval you can use mongoose populate
UPDATE:
if you don't want an xtra collection make your user schema something like:
var usersSchema = mongoose.Schema({
uname : {type : String , unique: true},
email : {type : String},
logintype : {type : String},
password : String,
status : String,
hash : String,
social: {},
games: Object,
os: String,
friends: Object,
msges: [{
id : Schema.Types.ObjectId,
from : String,
title: String,
msg : String,
send_on : Date,
read_on : Boolean }]
});
But keep in mind that if you also want the message to be present with the user who sended it you need to put it in the array by both users (keep id equal).... So you should think / talk about the best solution in your scenario.

how to unwind in moongose after populate

I have two schemas, Mails and Users, as defined here:
var MailsSchema = new Schema({
from : [{ type: ObjectId, ref: 'UsersSchema' }],
to : [{ type: ObjectId, ref: 'UsersSchema' }],
date : { type: Date, default: Date.now },
subject : { type: String, default: '' },
message : { type: String, default: '' },
isRead : { type: Boolean, default: false }
});
var UsersSchema = new Schema({
username : String,
pass : String,
firstName : String,
lastName : String,
age : Number
});
I want to get list of mail that send to specific user, populate the username in 'from' field,
I tried to do it that way:
mails.find({ to: id }).populate('from', 'username').exec(function (err, docs)...
The problem is:
I'm getting an array in 'from' field, I want to get only the username.
I.e. instead of getting this result:
[{"_id":"53fa2902da480e4c0d315fcd","__v":0,"isRead":false,"message":"SABABA","subject":"MA KORE","date":"2014-08-24T18:03:46.428Z","to":["53f9dbe164b1375c1c5b997a"],"from":[{"_id":"53f9dbe164b1375c1c5b997a","username":"adaroh"}]}]
I want to get that result:
[{"_id":"53fa2902da480e4c0d315fcd","__v":0,"isRead":false,"message":"SABABA","subject":"MA KORE","date":"2014-08-24T18:03:46.428Z","to":["53f9dbe164b1375c1c5b997a"],"from":"adaroh"}]
That's just how populate works. You can modify the docs yourself to filter out the extra id. In your exec, for each doc that gets populated you can look at the from array and do
doc.from[i] = doc.from[i].username