If you had a collection as such.
user {
name: String,
email: String,
information: String
}
You would do something like so to get a list of all John's that have information of doctor.
db.user.find({name: "John", information: "doctor" });
Now this makes the code redundant when having variable inputs. Such as having permutations of fields to filter. I'm trying to make my query generic, such as this bad broken example.
Therefore I might want to be able to explicitly state fields that can match any value. The following examples should return the same documents in theory.
Example:
Un-Explicit (normal) db.user.find({});
Explicit (weird) db.user.find({name: {$ANY}});
Or make it even more complex.
db.user.find({name: {$ANY}, information: "doctor"});
This would not work, but the intention is to get all the documents that are doctors but have ANY sort of value on the name field, not just for John's. Maybe even something more complex like so.
db.user.find({name: function(){
if(req.query.name)//check if empty
{ return req.query.name; }
else { return $ANY; }
}, information: "doctor"});
This would then be generic enough to use a single query instance for dynamic request behavior.As far as I know there isn't anything like this implemented.
Thank you in advance.
To get all the documents that are doctors but have ANY sort of value on the name field, you need the $exists and $ne operators in your query, since the $exists operator matches the documents that contain the field, including documents where the field value is null and the $ne operator selects the documents where the name field is not null:
db.user.find({"name": { "$exists": true, "$ne": null }, "information": "doctor"});
If you want to find all the documents with information = 'doctor', why not just query without the name?
db.user.find({information: "doctor" });
Related
I have an Mongoose database object which contains a collection that holds "user signatures", where the signature is must to be unique, i.e no duplicates of signatures can appear in the collection.
I have therefor put the unique: true flag on the field signature in the schema object, but this still don't prevents it from having duplicate, but it do work on title
query
You can modify your filter and include $elemMatch condition to make sure that the element you're trying to insert into an array isn't already there:
let filter = { _id: id, signatures: { $not: { signature: signature } } };
Mongo Playground example
So if you're trying to insert a new signature the document will be found by _id otherwise the filter part will return no matching document and your update won't be applied.
I have using nodeJS and mongoose/mongoDB to build an API. Consider the following model for a generic Model (Gmodel):
{
name: "teleni",
type: "person",
data: mixed
}
The data field in this document is a mixed type so it can be anything, but I intend for it to be a subdocument/object in most cases (depending on the value of the type field). If I wanted to find all the documents that were of type person I would execute the following code:
Gmodel.find({type: "person"}, callbackFunction)
Now consider another instance of the Model:
{
name: "teleni",
type: "person",
data: {
data_type: "event",
date: "Jan 30 2019"
}
}
My issue is that I want to use mongoose to find all documents where the data field is an object/document where the data_type field is "event". I have tried the following code:
Gmodel.find({data: {data_type: "event"}}, callbackFunction)
However nothing is returned when I execute this code because find is looking for Documents where the data field is exactly {data_type: "event"}. So how do I use find to retrieve Documents whose subdocuments (of mixed type) partially match a criteria, similar to how find works on top level fields.
You can use the dot syntax data.data_type to specify a field in subdocument. This way it would match on the basis on this field only, not the entire subdocument as in your original code.
Gmodel.find({data.data_type: "event"}, callbackFunction)
I have to run a dynamic query on collections in such a way that user enters collection name, field name and field value and I have to first of all check whether the field name supplied by user exists in the collection , if not then I have to run another query as shown in the example below.
For example:
If user enters collection name user, field name is type and field value is article. And based on parameters I have to query as follows:
1) If type field exists in collection user, my query will be:
query = user.find({type:'article'})
2) If type is not field of collection user, my query will be:
query = user.find()
I tried $exists but it is not working for me. And how can I use $exists before querying? because my collection, field name and field value all are dynamic.
And How can I check that type field exists or not in user collection?
I already tried the solution with $exists, but I want to know if there is another way to do it.
As #Philipp mentioned in his comment, you are bound to bump into performance issues as you would need to perform a full-collection scan without the use of indexes. Using $exists, the query will return fields also equal to null. Suppose you want to first find all records who have the field type set and isn't null, then use a combination of the $ne operator. The closest you could try is get the count of that field and then determine the query object based on the field count:
var type_count = db.user.find({"type": {$exists: true, $ne: null}}).count();
var query = (type_count > 0) ? {"type": "article"} : {};
db.user.find(query);
I'm searching on Google since days and I tried many things but I still can not perform a good full text search on my user collection.
I tried ElasticSearch but was pretty impossible to query and paginate...
I tried many plugins for Mongoose like ElMongo, mongoose-full-text, Mongoosastic, etc... everyone are really bad documented and I don't know how to perform a good full text search.
So, my collection is a normal collection:
user = {
name: String,
email: String,
profile: {
something: String,
somethingElse: String
}
}
I have a search input in a page with a simple POST, if I type hello world what I need is to search on the entire collection fields the matching words of my search query and get the results.
It will be really nice also to have options to handle a pagination like 10 items per page or something...
What is the best solution to achieve this? I'm using MongoDB 2.6.* with Mongoose, NodeJS and ExpressJS.
Thanks.
You can add a text index to your Mongoose schema definition that lets you use the $text operator in your find queries to search all fields included in the text index.
To create an index to support text search on, say, name and profile.something:
var schema = new Schema({
name: String,
email: String,
profile: {
something: String,
somethingElse: String
}
});
schema.index({name: 'text', 'profile.something': 'text'});
Or if you want to include all string fields in the index, use the '$**' wildcard:
schema.index({'$**': 'text'});
This would enable you to perform a paged text search query like:
MyModel.find({$text: {$search: searchString}})
.skip(20)
.limit(10)
.exec(function(err, docs) { ... });
For more details, read the full MongoDB Text Indexes documentation.
This is not an extra answer but an addUp, but if the above answer by JohnnyHK is giving you an empty array [] .
Try something basic first without limit and skip
const results = await MyModel.find({ $text: { $search: "text" } });
Please check if the index was created properly using mongosh using
db.stories.getIndexes() or compass GUI both attached. Else create one via COMPASS GUI or via mongosh using docs
Then try changing searchText multiple times and try.
Even after all this it took me 7- 8 runs of same code to get proper results,
I have this field which is working as I want
tagSlug: {
type: String,
label: "slug",
optional:true,
autoValue: function() {
if (this.siblingField('tag').isSet) {
return URLify2(this.siblingField('tag').value);
}
}
}
But I also want to make another field named nameSlug which needs two fields to be slugged, _id and title if I use this.siblingField('title').value I get title value but nothing hapens if I use this.siblingField('_id').value this may be because _id is not a field inside the form... The final output I want is something like this this-is-awesome-title-xDux1if the last param is _id cutted to 6 or 7 characters I don't know what I will do yet in order to not create large slug strings, but you get the idea.
So basically what I want is to access _id field from inside collection for autoValue another field.
I'm using meteor-autoform so I didn't create any Whatever.insert method because they're created automaticaly.
If you don't need to store it, you can use virtualfields or collection-helpers