Please i am trying to wrap my head over how to query a collection dynamically. I have a collection that has the below schema.
Tripart_Property_Schema = new SimpleSchema({
"type" : {
type : String,
label : 'Property type',
},
"sale_lease" : {
type : String,
label : '',
},
"location" : {
type : Object,
label : '',
optional : true
},
"location.state" : {
type : String,
label : 'state',
},
"location.lga" : {
type : String,
label : 'lga',
optional : true
},
"location.address" : {
type : String,
label : 'address',
optional : true
},
"amount" : {
type : Object,
label : '',
optional : true
},
"amount.amount" : {
type : Number,
label : '',
optional : true
},
"amount.discount" : {
type : Number,
label : '',
optional : true
},
"active" : {
type : Boolean,
label : '',
optional : true
},
"views" : {
type : Number,
label : '',
optional : true
},
"date_added" : {
type : Date ,
label : '',
optional : true
},
"general_features" : {
type : [String],
label : '',
optional : true
},
"outdoor_features" : {
type : [String],
label : '',
optional : true
},
"indoor_features" : {
type : [String],
label : '',
optional : true
},
"other_facilities" : {
type : Object,
label : '',
optional : true
},
"other_facilities.bedroom" : {
type : Number,
label : '',
optional : true
},
"other_facilities.bathroom" : {
type : Number,
label : ' ',
optional : true
},
"other_facilities.garage" : {
type : Number,
label : '',
optional : true
},
"other_facilities.staffQuaters" : {
type : Number,
label : '',
optional : true
}
});
I have created a user interface where a user can query the data using any combination of the available fields. A user can make a query searching for a property by using the sale_lease field, amount.amount field and also query the general_features field which is an array. I don't know how to generate this query based on the user selected preference. I know how to perform the query knowing the fields queried before hand, but making it dynamic is where the problem lies.
I am trying to make use of multiple if statements to possibly make a query for all possible combination of fields, but i kind of realize that this is not the way to achieve this. I will be very grateful if i can be pointed to the right direction.
Let's take the simple case where your collection has several keys, the user can query on any combination of them, and you want to AND the results. A typical pattern would be:
let query = {}'
if ( $("#type").length ) query.type = $("#type").val();
if ( $("#sale_lease").length ) query.sale_lease = $("#sale_lease").val();
if ( $("#state").length ) query.location = { state: $("#state").val() };
return Tripart_Property.find(query);
For simplicity, the above assumes that you've given each search field an ID equal to the corresponding schema field. Your naming convention may vary.
As you can see, you start with a blank query object then look at each search field, if it is non-blank then you add a key to the query corresponding to the schema key you want to search on.
With good naming conventions and a simple field structure you can even do this in a js loop so you don't need one if statement per key.
Without knowing the specifics of how users are able to make a selection for the query, the name of the collection, etc, it's difficult to provide a detailed example; however, you should be able to take the user's selection and turn it into a query parameter object. For example, assuming the collection name is Tripart_Property, if the user makes a selection for the sale_lease field, you could do the following:
var saleLeaseSelection = argumentContainingSelectionFromUser;
var customQuery = { sale_lease: saleLeaseSelection };
Tripart_Property.find(customQuery);
This is a very basic example. argumentContainingSelectionFromUser is the data from the user selection. You would probably want to build a method on the server that you could call from the client that would return the results from the query so that you could display them to the user, but this should at least get you pointed in the right direction.
Related
i'm currently trying to reference a collection called items with the structure below
packageSchema = schema({
recipient: String,
contents: [{item :{type: mongoose.Schema.Types.ObjectId,
ref: 'items', required : true}, amount: String}]
Below is my code for getting one package via its id
getOnePackage : function(id,callback)
{
packageModel.findById(id,callback)
.populate('contents')
}
So when i call the above function i'm expecting to get this result
{
recipient : Dave
contents : [
{item : {
_id:5d2b0c444a3cc6438a7b98ae,
itemname : "Statue",
description : "A statue of Avery"
} ,amount : "2"},
{item : {
_id:5d25ad29e601ef2764100b94,
itemname : "Sugar Pack",
description : "Premium Grade Sugar From China"
} ,amount : "5"},
]
}
But what i got from testing in Postman is this :
{
recipient : Dave,
contents : []
}
May i know where did it went wrong? And also how do i prevent mongoose from automatically insert an objectId for every single element in the contents array....
Because element in contents array is object with item field so your populate should be:
.populate('contents.item')
Currently the data in mogo via mongoose is as below. I want to be able to iterate options once I pull it out of mongo.
currently if I save this record to a variable “record". I would need to do record.options[0].option1.check, I want to avoid [0].
I want to be able to just iterate over an object and be able to do the following.
record.option1.choice1
record.option2.choice2
my schema is
var questionSchema = new mongoose.Schema({
question: String,
question_slug: String,
options: []
});
{
"_id" : ObjectId("5832609483bf491db3d8faa1"),
"question" : “What is the capital of Illinois?",
"question_slug" : “what-is-the-capital-of-illinois",
"options" : [
{
"option1" : {
"check" : "on",
"choice" : “Springfield"
},
"option2" : {
"check" : "",
"choice" : “Chicago"
}
}
],
"__v" : 0
}
You can't define the schema for record.option1.choice1 and record.option2.choice2 since option1 and option2 seems to be dynamic.
But you can avoid [0] for record.options[0].option1.check by defining options as Object in the schema instead of array as below.
Hence, you can iterate over the object record.options with record.options.option1 and record.options.option2 etc.
var questionSchema = new mongoose.Schema({
question: String,
question_slug: String,
options: {
type: Object
}
});
{
"_id" : ObjectId("5832609483bf491db3d8faa1"),
"question" : “What is the capital of Illinois?",
"question_slug" : “what-is-the-capital-of-illinois",
"options" : {
"option1" : {
"check" : "on",
"choice" : “Springfield"
},
"option2" : {
"check" : "",
"choice" : “Chicago"
}
},
"__v" : 0
}
how can I return a specific value for a specific document in MongoDB? For example, I have a schema that looks like:
{
"_id" : "XfCZSje7GjynvMZu7",
"createdAt" : ISODate("2015-03-23T14:52:44.084Z"),
"services" : {
"password" : {
"bcrypt" : "$2a$10$tcb01VbDMVhH03mbRdKYL.79FPj/fFMP62BDpcvpoTfF3LPgjHJoq"
},
"resume" : {
"loginTokens" : [ ]
}
},
"emails" : {
"address" : "abc123#gmu.edu",
"verified" : true
},
"profile" : {
"companyName" : "comp1",
"flagged" : true,
"phoneNum" : "7778883333"
}}
I want to return and store the value for profile.flagged specifically for the document with _id : XfCZSje7GjynvMZu7. So far I have tried:
db.users.find({_id:'myfi3E4YTf9z6tdgS'},{admin:1})
and
db.users.find({_id: 'myfi3E4YTf9z6tdgS'}, {profile:admin});
I want the query to return true or false depending on the assigned value.
Can someone help? Thanks!
MongoDB queries always return document objects, not single values. So one way to do this is with shell code like:
var flagged =
db.users.findOne({_id: 'myfi3E4YTf9z6tdgS'}, {'profile.flagged': 1}).profile.flagged;
Note the use of findOne instead of find so that you're working with just a single doc instead of the cursor that you get with find.
The correct answer here is the method .distinct() (link here)
Use it like this:
db.users.find({_id:'myfi3E4YTf9z6tdgS'},{admin:1}).distinct('admin')
The result will be: 1 or 0
Hi I have a combo box which have a store that is based on rest call and populate data from data base, its working fine but i need a value 'All' with all the values coming from data base so how can i do this please suggest
var wardName = Ext.create('Ext.data.Store', {
id : 'visittype',
fields : [
{
name : 'id',
type : 'integer',
},
{
name : 'wardName',
}
],
remoteGroup : true,
remoteSort : true,
proxy : {
type : 'rest',
url : 'pmsRest/wards',
reader : {
root : "wardMaster",
idProperty : 'id'
}
},
autoLoad : true,
});
{
xtype : 'combo',
name : 'wardName',
labelStyle : 'color:black;font-weight:bold;width:250px;padding:10;',
labelSeparator : "",
id : 'wardName',
width:'33%',
fieldLabel : 'Ward',
triggerAction : 'all',
store : wardName,
displayField : 'wardName',
valueField : 'id',
multiSelect : false,
typeAhead : true,
//disabled: true,
listeners : {
change : function(combo) {
Ext.getCmp('bedName').bindStore(loadBedName());
}
},
allowBlank : false,
//enableKeyEvents : true,
},
Once the data from the proxy is loaded successfully you can use the insert method of store to add the static data in store.
insert method inserts Model instances into the Store at the given index.
The syntax is store.insert( index, records ) where index is the position at which you want to insert the instance, in this case it would be 0.
hope it helps you. :-)
Add a listener to the store and a load event. In that event you can add a new item to the store when the store is loaded.
listeners: {
load: function(){
this.add({
id: 0,
name: 'All'
});
}
}
I'm trying to change a type string to an Integer. The following code selects the right element when simply searching and the code works perfectly for string elements at the top.
db.providers.find({'assignments.assignment' :
{$elemMatch :
{
as_total_hours :
{$exists : true}}}}).forEach( function(obj) {
obj.as_total_hours = parseInt(obj.as_total_hours);
db.providers.save(obj);
})
Here is a sample of the document.
"dev_active_interviews" : 0,
"assignments" : {
"assignment" : [
{
"as_rate" : "$3.89",
"as_from" : "05/2011",
"as_to" : "Present",
"as_total_hours " : "16"
},
{
"as_rate" : "$2.22",
"as_from" : "11/2010",
"as_to" : "Past",
"as_total_hours" : "200"
}
]
}
Your code is assuming that the find returns the embedded assignment objects rather than the object.
Change :
obj.as_total_hours = parseInt(obj.as_total_hours);
db.providers.save(obj);
to
obj.assignments.assignment.forEach(function(obj) {
obj.as_total_hours = parseInt(obj.as_total_hours);
})
db.providers.save(obj);
You could also change the {$exists:true} to {$type: 2} (or combine them) so that the query only finds strings.