Below is the document:
{
name:"james",
files:[
{name:"file1.txt", content:"..."},
{name:"file2.txt", content:"..."},
{name:"file3.txt", content:"..."}
],
status:4
}
Want to make a query and return:
all root fields include files
files only contain file2.txt info, coze content is very big, only interested in files2.txt
I know using $elemMatch in find query, as below:
db.collection.find(
{'files':{$elemMatch:{name:'file2.txt'}} },
{name:1, status:1, 'files.$':1 }
)
Is there any way to avoid list all the fields in projection and get all the key?
Requirement: ask for all field but not to list the key (don't list name:1, status:1)
Is this what you asking for namely, return all the fields, but for the files field return only "files2.txt" value ?
db.collection.find({ 'files':{$elemMatch:{name:'file2.txt'}} }, { 'files.$':1, name:1, status:1 } )
Related
enter image description here
Let's say that we have many documents like this in the photo
I have the above schema. I want to find the document based on _id first and then push an array of values to providedServices which belongs to the _id which is inside barbers array
A little help. Can't seem to find this out!
You need to find the related arrays firstly. For this, you can use $elemMatch or write it as 'barbers._id' : {$elemMatch: parameter}' .
Here we tried to find document with filtering it's own id and barbers id. You can change the filter as you wished. It can be only search on barbers id.
Need to write your DocumentName and your parameters instead of idValue, barbersId, serviceModel.
const result = await DocumentName.findOneAndUpdate(
{
$and:
[
{_id: mongoose.Types.ObjectId(idValue)},
{'barbers': {$elemMatch: {_id: mongoose.Types.ObjectId(barbersId)}}}
]
},
{ $push: { 'barbers.$.providedServices': serviceModel } },
{ new: true })
At first, we found the related barbers array inside of all documents. Then we pushed the model inside of providedServices array into this barbers array.
how can I find all the documents that contains “Amazon” in any field as a value in MongoDB?.
Also, is it possible to search for the field and not the value? I heard you could do that but I am not sure how.
Thanks for the help.
You can use text index created on all string fields. You can create such index by using wildcard as below.
db.collection.createIndex( { "$**": "text" } )
In order to search the desired string, you can use
db.collection.find( { $text: { $search: "Amazon" } } )
Can anyone tell me how to add a $match stage to an aggregation pipeline to filter for where a field MATCHES a query, (and may have other data in it too), rather than limiting results to entries where the field EQUALS the query?
The query specification...
var query = {hello:"world"};
...can be used to retrieve the following documents using the find() operation of MongoDb's native node driver, where the query 'map' is interpreted as a match...
{hello:"world"}
{hello:"world", extra:"data"}
...like...
collection.find(query);
The same query map can also be interpreted as a match when used with $elemMatch to retrieve documents with matching entries contained in arrays like these documents...
{
greetings:[
{hello:"world"},
]
}
{
greetings:[
{hello:"world", extra:"data"},
]
}
{
greetings:[
{hello:"world"},
{aloha:"mars"},
]
}
...using an invocation like [PIPELINE1] ...
collection.aggregate([
{$match:{greetings:{$elemMatch:query}}},
]).toArray()
However, trying to get a list of the matching greetings with unwind [PIPELINE2] ...
collection.aggregate([
{$match:{greetings:{$elemMatch:query}}},
{$unwind:"$greetings"},
]).toArray()
...produces all the array entries inside the documents with any matching entries, including the entries which don't match (simplified result)...
[
{greetings:{hello:"world"}},
{greetings:{hello:"world", extra:"data"}},
{greetings:{hello:"world"}},
{greetings:{aloha:"mars"}},
]
I have been trying to add a second match stage, but I was surprised to find that it limited results only to those where the greetings field EQUALS the query, rather than where it MATCHES the query [PIPELINE3].
collection.aggregate([
{$match:{greetings:{$elemMatch:query}}},
{$unwind:"$greetings"},
{$match:{greetings:query}},
]).toArray()
Unfortunately PIPELINE3 produces only the following entries, excluding the matching hello world entry with the extra:"data", since that entry is not strictly 'equal' to the query (simplified result)...
[
{greetings:{hello:"world"}},
{greetings:{hello:"world"}},
]
...where what I need as the result is rather...
[
{greetings:{hello:"world"}},
{greetings:{hello:"world"}},
{greetings:{"hello":"world","extra":"data"}
]
How can I add a second $match stage to PIPELINE2, to filter for where the greetings field MATCHES the query, (and may have other data in it too), rather than limiting results to entries where the greetings field EQUALS the query?
What you're seeing in the results is correct. Your approach is a bit wrong. If you want the results you're expecting, then you should use this approach:
collection.aggregate([
{$match:{greetings:{$elemMatch:query}}},
{$unwind:"$greetings"},
{$match:{"greetings.hello":"world"}},
]).toArray()
With this, you should get the following output:
[
{greetings:{hello:"world"}},
{greetings:{hello:"world"}},
{greetings:{"hello":"world","extra":"data"}
]
Whenever you're using aggregation in MongoDB and want to create an aggregation pipeline that yields documents you expect, you should always start your query with the first stage. And then eventually add stages to monitor the outputs from subsequent stages.
The output of your $unwind stage would be:
[{
greetings:{hello:"world"}
},
{
greetings:{hello:"world", extra:"data"}
},
{
greetings:{hello:"world"}
},
{
greetings:{aloha:"mars"}
}]
Now if we include the third stage that you used, then it would match for greetings key that have a value {hello:"world"} and with that exact value, it would find only two documents in the pipeline. So you would only be getting:
{ "greetings" : { "hello" : "world" } }
{ "greetings" : { "hello" : "world" } }
Is there any way to remove all the documents except one from a collection based on condition.
I am using MongoDB version 2.4.9
You can do this in below way,
db.inventory.remove( { type : "food" } )
Above query will remove documents with type equals to "food"
To remove document that not matches condition you can do,
db.inventory.remove( { type : { $ne: "food" } } )
or
db.inventory.remove( { type : { $nin: ["Apple", "Mango"] } } )
Check here for more info.
To remove all documents except one, we can use the query operator $nin (not in) over a specified array containing the values related to the documents that we want to keep.
db.collections.remove({"field_name":{$nin:["valueX"]}})
The advantage of $nin array is that we can use it to delete all documents except one or two or even many other documents.
To delete all documents except two:
db.collections.remove({"field_name":{$nin:["valueX", "valueY"]}})
To delete all documents except three:
db.collections.remove({"field_name":{$nin:["valueX", "valueY", "valueZ"]}})
Query
db.collection.remove({ "fieldName" : { $ne : "value"}})
As stated above by Taha EL BOUFFI, the following worked for me.
db.collection.remove({"fieldName" : { $nin: ["value"]}});
You can see my document as bellow. How can I write a find for my uniq fields?
I need search a document where KEYMAP is (SNUM="3151" and "SKEY"="THR" and "SID"="ID_HUT")
{
"CID":"2",
"DESCRIPTION":"test",
"SECKEY":"test",
"API":{
"SMS":"http://api.php",
"DR":"http://api2.php"
},
"LOGS":{
"IN":"log_cid_in_1",
"OUT": "log_cid_out_1"
},
"KEYMAP":[
{"SNUM":"3151","SKEY":"THR", "SID":"ID_HUT"},
{"SNUM":"3152","SKEY":"ONE", "SID":"ID_XL"},
{"SNUM":"3153","SKEY":"TWO", "SID":"ID_INDO"}
]
}
db.content_provider_map.ensureIndex({"KEYMAP.SNUM":1,"KEYMAP.SKEY":1,"KEYMAP.SID":1},{unique:true});
db.mycollection.find({"KEYMAP.SNUM":"3151","KEYMAP.SKEY":"TWO","KEYMAP.SID":"ID_XL"});# not work. it find the document
I believe you want to use $elemMatch ( http://docs.mongodb.org/manual/reference/operators/#_S_elemMatch ) here like:
find({KEYMAP: {$elemMatch: {SNUM: "3151", SKEY: "TWO", SID: "ID_XL"}}})
Also unique indexes on subdocuments do not work the way you probably think they do. They create uniqueness across all documents not just that one document. If you want a unique index on that one document then you will need to use something like $addToSet or an upsert function on the subdocument.