Mongodb query select performing - mongodb

I'm trying to get this result:
{
facebookId: [
"123123", "321321", "999999"
]
}
But i get this result:
{
\"mobileUser\": {
\"facebookId\": \"1547339005533880\"
}
},
{
\"mobileUser\": {
\"facebookId\": \"958277234198503\"
}
},
{
\"mobileUser\": {
\"facebookId\": \"10201611922458772\"
}
}
My model:
var roomModelSchema = mongoose.Schema({
roomId: { type: String, index: true },
mobileUser: {
socketId: String,
facebookId: { type: String, index: true },
email: String,
name: String,
photoUrl: String,
genderType: String,
birthday: Date,
city: String,
likeCount: Number,
insertDate: Date
},
insertDate: Date
})
My query is:
Room.find({ "roomId": req.query.roomId }).select("mobileUser.facebookId -_id").exec(function(err, users) {
});
I'm work on it to know how mongodb query works. Because if i use to build this query in sql it's very easy. I have difficulties to understand it.

If you think about MongoDb in terms of SQL RDBMS, each mongodb document corresponds to row in SQL DB.
So for example if you execute in SQL
select * from myTable
you will get
facebookID | name | city
--------------------------------
13453 | A | A
2213 | B | B
312321 | C | C
and if you do the simialr query in mongo
db.myTable.find({})
you will get
{facebookId: 13454, name: A, city: A},
{facebookId: 2213, name: B, city: B},
{facebookId: 312321, name: C, city: c},
So now if you query for one field and execute in SQL
select facebookId from myTable
you will get
facebookID
----------
13453
2213
312321
And in mongoDb, if you execute
db.myTable.find({}, {id:false, faceBookId: true})
{id:false, faceBookId: true} - correspond to select methods from Mongoose. It specifies what fields should be included in documents
you will get
{facebookId: 13454},
{facebookId: 2213},
{facebookId: 312321},
If you would like to get these fields from multiple documents and output single document with facebookId field that contains all values, you can use aggregate framework
db.myTable.aggregate(
{$group:{_id:null, facebookId:{$addToSet:'$Name'}}}
)
This will return:
{
_id: null,
facebookId: [
"13454", "2213", "312321"
]
}

Related

Query in command must target single shard key

I have an array of document ids using which I wish to delete the documents with the given id. The document id is also the shard key of the document. So I provided the following query for model.deleteMany(query)
query:
{ doc_id: { '$in': [ 'docid1', 'docid2' ] } }
I still get the error Query in command must target single shard key.
Is it possible to overcome this without looping through the array and deleting the docs one by one?
By matching any document in the collection with the _id field, you can make a query or delete command:
db.collection.deleteMany({ _id: { $exists: true }})
During the specification of the schema model in the code, a Shard Key (Partition Key) must be specified. We may execute operations such as save, update, and delete once it is provided
const mySchema = new Schema({
requestId: { type: String, required: true },
data: String,
documents: [{ docId: String, name: String, attachedBy: String }],
updatedBy: {
type: {
name: { type: String, required: true },
email: { type: String, required: true },
}, required: true
},
createdDate: { type: Date, required: true },
updatedDate: { type: Date },
}, { shardKey: { requestId: 1 } }
);

How to define a unique field in mongoose schema?

My Schema is like below:
const schema = new mongoose.Schema({
a: {
b: { type: String, unique: true },
c: { type: String }
},
aa: {
bb: [{
cc: { type: String, unique: true },
dd: { type: String }
}]
}
})
now I want to 'b' and 'cc' fields be unique.
how can i do this?
I added this code at the end of the top code, but the schema allows duplicate values.
schema.index({'a.b':1}, {unique:true})
schema.index({'aa.bb.cc':1, {unique:true})
Do you have any idea to solve this problem?
try adding dropDups as shown below.
const schema = new mongoose.Schema({
a: {
b: { type: String, unique: true, dropDups: true },
c: { type: String }
},
aa: {
bb: [{
cc: { type: String, unique: true, dropDups: true },
dd: { type: String }
}]
}
})
if it doesn't work try: -
const schema = new mongoose.Schema({
a: {
b: { type: String, index: { unique: true, dropDups: true } },
c: { type: String }
},
aa: {
bb: [{
cc: { type: String, index: { unique: true, dropDups: true } },
dd: { type: String }
}]
}
})
The answer here depends on exactly what you mean by "I want to 'b' and 'cc' fields be unique."
Mongoose implements the unique constraint by creating a MongoDB index on that field with the unique:true option.
MongoDB enforces the unique option by not allowing the same value to be stored twice in the index.
When a document is written to MongoDB, it extracts the field values from the document that are required by the index, deduplicates the list, and then stores the values in the index with a pointer to the document.
This means that only 1 document may contain a specific value, but that document may contain that value many times.
For example:
If there is an index on {i:1}, these sample documents would have the following entries in the index:
Document
Index entries
{i:1}
1=>
{i:[2,3,4]
2=>
3=>
4=>
{i:[5,6,5,6,5]}
5=>
6=>
{i:[2,6]}
2=>
6=>
If the index were unique, and the documents were inserted in exactly that order, the first 3 documents would be perfectly acceptible, and the last would result in a duplicate key error.

MongoDB: Best way query users by given names and username

I'm trying to implement a user search that looks into the user's given names and their username, while also being able to sort results by relevance.
I tried creating a text index like this
db.users.createIndex({
username: 'text',
firstName: 'text',
lastName: 'text'
},
{
name: 'text_search',
default_language: 'en',
language_override: 'language'
})
But this doesn't take into account partial terms, so if I search for "Juan F", I get the following results
{ score: 3.7, username: "juanjo", firstName: "Juan", lastName: "Rivas F" },
{ score: 2.95, username: "Juan.rodriguez", firstName: "Juan", lastName: "Rodriguez" },
{...} // 6 more
{ score: 2.2, lastName: "Fuentes", firstName: "Juan", username: "juanfuentes" }
I understand that text indexes take into account similar words, but not partial terms, so with "Juan Fuente" I get the desired result, with "Juan F", "Juan Fu", etc, I don't.
Is there a way to improve this, in order to be able to implement a search that returns results as the user types into a search box?
Edit This is the query I tried:
db.users.find(
{ $text: { $search: "juan f" } },
{ score: { $meta: "textScore" } }
).sort({ score: { $meta: "textScore" } })

What's a good way to look up list of enumerated values?

I have a collection of case with a field named status (integer) whose valid values are 0, 1, 2, 4 and 8, representing "New", "WIP", "Solved", "Canceled" and "Closed" respectively.
So, in mongoose syntax, it might be like:
const caseSchema = new Schema({
createdOn: Date,
subittedBy: String,
status: Number,
...
});
const statusSchema = new Schema({
value: Number,
description: String
});
Is this a good way to organize the data? How do I make a query to retrieve cases with the status field properly filled with the description?
It is one way to do it sure. You could do the query by using $lookup. It would look something like this:
db.getCollection('<YourCasesColName>').aggregate([
{ $match : { 'status' : 1 } }, // or { $in: [1,2,3] },
{
$lookup: {
from: '<YourStatusColName>',
localField: 'status',
foreignField: 'value',
as: 'statusDoc',
}
}
])
Another way is to add a reference to the actual status via ObjectId so that instead of numbers in the cases you would be storing references to the actual Status objects and in this way have a better referential integrity. However you would still need to do similar query to get both in one shot. So here is what I am talking about:
const caseSchema = new Schema({
createdOn: Date,
subittedBy: String,
status: { type: mongoose.Schema.Types.ObjectId, ref: 'Status' },
// ^ now your status hows reference to exactly the type of status it has
});
const statusSchema = new Schema({
value: Number,
description: String
});
So the actual data would look like this:
// Statuses
[{
_id: <StatusMongoObjectID_1>,
value: 1,
description: 'New'
},{
_id: <StatusMongoObjectID_2>,
value: 2,
description: 'New'
}]
// Cases
[{
_id: <MongoObjectID>,
createdOn: '<SomeISODate>',
subittedBy: '<SomeString>',
status: <StatusMongoObjectID_1>
},
{
_id: <MongoObjectID>,
createdOn: '<SomeISODate>',
subittedBy: '<SomeString>',
status: <StatusMongoObjectID_2>
}]

MongoDB using mongoose for populate

I am having collection1 with one of the column as ref of collection2. Now i want to populate(join) collection1 and collection2 with some condition on collection2 fields. Is it possible?
What i want to do is
models.Encounter
.where('practice').equals(practice)
.populate({
path:'chart',
match:{firstName:{ $regex: new RegExp(Name.toLowerCase(), 'i') }},
select:'firstName lastName'})
.populate('provider', 'firstName lastName')
.populate('signedBy', 'firstName lastName')
.sort('-date')
.limit(100)
.exec(function (err, encounters) {})
Here charts is collection and for me match is not working..Where Name comes from jade engine. null values are coming for firstname
Practice Schema:
The schemas are
var practiceSchema = mongoose.Schema({
name: String,
internalName: String,
address: addressSchema,
phone: String,
taxId: String
});
Chart Schema:
var chartSchema = mongoose.Schema({
created: Date,
updated: Date,
practice: {type: mongoose.Schema.ObjectId, ref : 'practices', required: true},
mrn: String,
firstName: String,
lastName: String,
emailWork: String,
phoneHome: String,
phoneMobile: String,
dob: Date,
married: Boolean,
smoker: Boolean
});
Now i want to get data from Encounters by populating charts and also charts.firstName == 'XYZ' and charts.lastName == 'ABC'.. I have done this by getting all data from encounters and then applying filter on charts. But it is taking too much of time..