Find a Document where value matched in either field using Mongoose Middleware - mongodb

I have a list of account connections between source and target accounts so my schema looks like
var ConnectionRequestSchema = new Schema({
sourceAccountId: {
type: Schema.ObjectId,
ref: 'Account'
},
targetAccountId: {
type: Schema.ObjectId,
ref: 'Account'
},
status: {
type: String,
enum: ['pending', 'accept', 'decline'],
trim: true
}
});
I want to query all documents where the sourceAccountId or the targetAccountId are equal to the queried accountId.
I saw this link how-to-find-a-document-where-either-one-or-another-field-matches-a-value which is relevant for find a docouments using the stand find method in Mongo.
User.findOne({
$or: [
{first_name: name},
{last_name: name},
],
}, function(err, user) {
})
But I would like to do this using Mongoose Middleware and I'm not sure how I would construct this condition.

already you figured out the solution, but you have to make some changes in query
ConnectionRequest.find({
$or: [
{sourceAccountId: "5736eac90a39c2547cb9d911"},
{targetAccountId: "5736eac90a39c2547cb9d911"},
],
}, function(err, connection) {
console.log(connection)
})
then finally you will get the result is array of documents

Related

Optimizing query that makes 3 API calls to the MongoDB server

const user_schema = mongoose.Schema(
{
user_name: {
type: String,
required: true,
},
},
{
collection: `user`,
timestamps: true,
}
);
const test_schema = mongoose.Schema(
{
test_name: {
type: String,
required: true,
},
},
{
collection: `test`,
timestamps: true,
}
);
const score_schema = mongoose.Schema(
{
user_id: {
type: mongoose.Schema.Types.ObjectId,
ref: "user",
required: true,
},
test_id: {
type: mongoose.Schema.Types.ObjectId,
ref: "test",
required: true,
},
test_score: {
type: Number,
required: true,
},
},
{
collection: `score`,
timestamps: true,
}
);
query:
Given an array of user_id and an array of test_id, query the score model to find out the test scores.
To get the array of user_id, a set of conditions is given and the user model must be queried to find the set of users matching the conditions.
To get the array of test_id, a set of conditions is given and the test model must be queried to find the set of tests matching the conditions.
What needs to be done:
Make one query request to the MongoDB server to get the array of user_id.
Make a separate query request to the MongoDB server to get the array of test_id.
Make another query request to the MongoDB server to get the test scores:
db.getCollection("score").aggregate([
{$match: {$and: {user_id: {$in: array_of_user_id}, {test_id: {$in: array_of_test_id}}}}}
])
Is this the most optimal way to get the test scores? Is it possible to make just one request to the MongoDB server?

Documents inserted without schema not being found with schema

I have two new collections in MongoDB of data that I pulled from an old Firestore database that I'm moving to mongo. Since the total number between these two collections is roughly 20,000, I opted to paste the raw JSON into the insert document section in mongo, which worked like a charm and I didn't have to write a new insert route to do the same.
I then created a schema in Mongoose that matched the inserted documents, and tried to use the schema to pull back some data, and its always returning nothing.
An example of a ticket inserted via JSON:
{
"title": "How to add and manage users for your company in QuickBooks Online",
"priority": "1",
"type": "Video",
"course": "G205",
"transcriptId": "07dom27Zz98jakvB1oh5",
"status": "In Review",
"tags": "",
"url": "",
"revisionNumber": 0,
"directoryId": 19,
"checkedOut": false
},
And my schema I made to match. The collection name in mongo is also called oldTickets, the plural of my schema name here:
const mongoose = require('mongoose');
var Schema = mongoose.Schema
const schema = new Schema({
course: { type: String },
title: { type: String },
priority: { type: String },
type: { type: String },
course: { type: String },
transcriptId: { type: String },
status: { type: String },
tags: { type: String },
url: { type: String },
revisionNumber: { type: Number },
directoryId: { type: Number },
checkedOut: { type: Boolean },
});
module.exports = mongoose.model('oldTicket', schema);
And finally my model import and fetch call:
const OldTicket = require('./models/model_old_ticket');
/***************************************************************************
* Get Old Tickets - Returns all old tickets, 10 at a time
****************************************************************************/
app.get('/getOldTickets/:offset', (req, res) => {
checkConnection();
OldTicket.find().skip(parseInt(req.params.offset)).limit(10).exec((err, data) => {
if (err){ res.status(500).send({err: err}); }
//If we got data, count the tickets & return the tickets & count
if (data) {
OldTicket.find().countDocuments().then(count => {
return res.status(200).send({
tickets: data,
count: count
})
})
}
});
});
Why isn't this finding anything? Both the count and the tickets are 0. I've run into this issue before when manually creating a collection without a schema, and in those instances I would simply delete the collection, write a route to create a document, and then things would work fine. But with the large data size of these two collections, I'd rather not do that since everything should be working as is.
Edit: Example of document in Mongo
And the name of the collection I'm currently viewing:
And I just now realized that for some reason there are now two collection names, oldTickets, which has data, and oldtickets, which is empty. I'm assuming my query is searching through the empty one? How can I get it to go to the one that actually has data?
can you attach the screenshot of your data with the collection? might be it's different.in mongoose, every collection name is complete with 's'. please verify your collection is created manually by you then it has to same as mongoose schema and also completed with 's'.
example:
const mongoose = require("mongoose");
const schema = new mongoose.Schema(
{
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
index: true
},
filmId: {
type: mongoose.Schema.Types.ObjectId,
index: true
},
filmType: {
type: String,
index: true
},
birthday: {
type: Date
},
age: {
type: Number
},
terms: {
type: Boolean
}
},
{
versionKey: false,
timestamps: true,
}
);
schema.index({ filmId: 1, user: 1 })
module.exports = mongoose.model("UserAgeVerification", schema);
see my database

GraphQL Mutation Updating Users Followers with Mongoose/MongodDB - $set is empty error

I have this mutation set up:
followUser: {
type: UserType,
args: {
_id: { type: GraphQLString },
firebaseUid: { type: GraphQLString },
following: { type: new GraphQLList(GraphQLString)},
},
resolve(parentValue, { firebaseUid, _id, following}) {
const update = {
$set: { "following": [firebaseUid] },
$push: { "following": { firebaseUid } }
}
return UserSchema.findOneAndUpdate(
{ _id },
update,
{new: true, upsert: true}
)
}
},
I'm trying to add new followers into my graphql user's collection. My user model:
const UserSchema = new Schema(
{
firebaseUid: String,
following: [{ type: Schema.Types.ObjectId, ref: 'User' }],
followers: [{ type: Schema.Types.ObjectId, ref: 'User' }],
},
{ timestamps: true }
);
module.exports = mongoose.model("User", UserSchema);
So at first, the user doesn't have any followers, so it won't have that field yet. When user adds someone to their friends list, thats when the field will appear in mongodb. Right now I'm getting this error:
"message": "'$set' is empty. You must specify a field like so: {$set: {<field>: ...}}",
I'm not sure if I'm doing the $set correctly.
The UserType
const UserType = new GraphQLObjectType({
name: "User",
fields: () => ({
_id: { type: GraphQLString },
firebaseUid: { type: GraphQLString },
following: { type: new GraphQLList(GraphQLString) },
followers: { type: new GraphQLList(GraphQLString) },
...
})
});
edit:
current mongodb data collection:
_id: ObjectId("5e5c24111c9d4400006d0001")
name: "Mr. Smith"
username: "mrsmith"
after running the update
_id: ObjectId("5e5c24111c9d4400006d0001")
name: "Mr. Smith"
username: "mrsmith"
following: ["fdsaduybfeaf323dfa"] // <-- this gets added
Currently mongooses validator is rejecting the update. To fix this you need the following:
You only need to $push since it will automatically create an array if the property does not exist
You should remove the extra { } around the firebaseUid in the $push because otherwise the following array will contain objects with a firebaseUid property instead of directly containing the Uid (or would if the schema validator allowed it)
Mongo ObjectIds can only be converted from strings when they are 12-byte hexadecimal, and firebaseUid is not, so the schema should be typed to String instead of ObjectId as the validator will reject the field for update otherwise.

Ensure a unique index on nested reference on a mongoose schema

What I want is that a user can like a post only once, hence I uniquely indexed the user in the likes array to ensure the same, but it isn't working and I can't find out what is wrong here .
The schema looks like this :
const mongoose = require('mongoose')
const postSchema = new mongoose.Schema({
author: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User' // User model
},
text: {
type: String,
required: [true, 'Post must have some text']
},
likes: [
{
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
}
}
],
comments: [
{
author: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
text: {
type: String,
required: [true, 'Comment must have some text']
},
addedAt: {
type: Date,
default: Date.now
}
}
],
createdAt: {
type: Date,
default: Date.now
}
})
postSchema.pre(/^find/, function(next) {
this.populate({
path: 'author',
select: 'name avatar'
}).populate({
path: 'comments.author',
select: 'name avatar'
})
next()
})
// Ensure a user can like a post only once
postSchema.index({ 'likes.user': 1 }, { unique: true })
const Post = mongoose.model('Post', postSchema)
module.exports = Post
However when I send a post request to like a post twice via the same user it
shows no error.
Here is the postman output
I have tried both the ways listed in this, but none of them worked in this case.
Mongoose Index on a field in nested document
How do I ensure a user can like a post only once from the schema itself ?
Try saving likes in this format in the database
likes:[{type:mongoose.Schema.Types.ObjectId,ref: 'User'}]
making it
likes:[ObjectId("5af03111967c60501d97781f")]
and when the post like API is hit do
{$addToSet: {likedBy: userId}}
in update query,addToSet ensures no duplicate ids are maintained in the array.

Populate query with match returns null

I have three schemas, that need them to be separated and I can't use subdocuments. The important one is this
export var TestSchema = new mongoose.Schema({
hash: { type: String, index: { unique: true }, default: common.randomHash },
date: { type: Date, default: Date.now },
result: { type: Object },
user: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
data: { type: Object },
finished: Date,
lang: { type: String, default: 'pt' },
benchmark: { type: String, required: true },
order: { type: mongoose.Schema.Types.ObjectId, ref: 'Transaction' },
/* TODO: remove */
name: { type: String }
});
I have a query that does the populate (it's actually a pagination helper, but I'm cutting to the chase):
TestModel.find({hide: {$ne: true}, user: id}).populate({
path: 'user',
match: {$or: [
{email: new RegExp(search, i)},
{name: new RegExp(search, i)},
{empresa: new RegExp(search, i)},
]}
}).exec().then(/*...*/)
when populate.match doesn't find anything, it sets the user to null. I tried setting the find({'user':{$ne: null}}) but it ignores it. (I guess the populate happen after the find call, maybe that's the reason).
Is there any way I can filter it in the database layer instead having to rely on iterating of the results, check for null then filter out?
This answer on GitHub clarifies that it is not possible with populate, due to how MongoDB works. However, you should be able to do it with $lookup.