i am confuse.
here is the example:
MongoDB Enterprise > db.employee.find()
result:
{"_id":1002,"name":"Jack","address":{"previous":"Cresent Street","current":"234,Bald Hill Street","unit":"MongoDB" } }
I try this:
db.employee.find({address:{previous: "Cresent Street"}})
result: nothing returns
Next a try this:
db.employee.find({"address.previous": "Cresent Street"})
result:
{"_id":1002,"name":"Jack","address":{"previous":"Cresent Street","current":"234,Bald Hill Street","unit":"MongoDB"}}
The question is wath is wrong with this?
i use
MongoDB shell version v4.2.7 installed
cmd db.version() 4.2.6
debian 10.4
thanks for your replies.
When you Query on Embedded/Nested Documents using dotted field notation
{"address.previous": "Cresent Street"}
means find a document that containd an address field that contains a document whose previous field is equal to "Cresent Street".
When you provide a subdocument like
{address:{previous: "Cresent Street"}}
this means to find a document that contains an address field whose content is exactly the document {previous: "Cresent Street"}, with no additional fields. If you provide multiple fields in the subdocument, field order also matters.
Both of these queries are useful in specific scenarios, pick the one that does what you need in your situaion.
Related
I am using PyMongo to insert data (title, description, phone_number ...) into MongoDB. However, when I use mongo client to view the data, it displays the properties in a strange order. Specifically, phone_number property is displayed first, followed by title and then comes description. Is there some way I can force a particular order?
The above question and answer are quite old. Anyhow, if somebody visits this I feel like I should add:
This answer is completely wrong. Actually in Mongo Documents ARE ordered key-value pairs. However when using pymongo it will use python dicts for documents which indeed are not ordered (as of cpython 3.6 python dicts retain order, however this is considered an implementation detail). But this is a limitation of the pymongo driver.
Be aware, that this limitation actually impacts the usability. If you query the db for a subdocument it will only match if the order of the key-values pairs is correct.
Just try the following code yourself:
from pymongo import MongoClient
db = MongoClient().testdb
col = db.testcol
subdoc = {
'field1': 1,
'field2': 2,
'filed3': 3
}
document = {
'subdoc': subdoc
}
col.insert_one(document)
print(col.find({'subdoc': subdoc}).count())
Each time this code gets executed the 'same' document is added to the collection. Thus, each time we run this code snippet the printed value 'should' increase by one. It does not because find only maches subdocuemnts with the correct ordering but python dicts just insert the subdoc in arbitrary order.
see the following answer how to use ordered dict to overcome this: https://stackoverflow.com/a/30787769/4273834
Original answer (2013):
MongoDB documents are BSON objects, unordered dictionaries of key-value pairs. So, you can't rely on or set a specific fields order. The only thing you can operate is which fields to display and which not to, see docs on find's projection argument.
Also see related questions on SO:
MongoDB field order and document position change after update
Can MongoDB and its drivers preserve the ordering of document elements
Ordering fields from find query with projection
Hope that helps.
Good evening.
I have this MongoDB document.
This document contains information about M. Allegri, an italian coach. The array coached_Team contains all teams that Allegri coached. In this example there is just one team, but it's just a test; one coach has a lot of team in coached_Team array.
Is there a way to update the palmarès of just one team? For example, Juventus last year won 1 Serie A and 1 Coppa Italia.
This query, clearly, does not work because in that array there will be palmarès of all teams that Allegri coached:
db.coach.update({_id:"MA_1967"}, {$set: {"coached_Team.palmarès.Serie A":33}})
So, I thought to use a normalized model instead of denormalized. But I want to know if there is a way to update the palmarés of Juventus, for example, using this denormalized pattern.
Thank you.
Yes you can using the MongoDB positional operator in your update statement. The $ positional operator has some caveats to read up on but you could write your query like this.
db.coach.update({_id:"MA_1967", 'coached_Team': "Juventus"}, {$set: {"coached_Team.$.palmarès.Serie A":33}})
in order to use the $ positional operator you have to include one and only one array attribute in your find. The $ will then match only the first element in the array that matches the document you are looking for. So your update statement reads something like 'set the first item in coached_Team that matched my array query' then you access the palmares and Serie A attribute through the $ positional operator. The $ and elemMatch operators are very powerful, but unfortunately sometimes very confusing, operators to read up on in MongoDB.
I need to find all the documents in mongodb that have keywords that start with number 1-9, then add a '+' in front of the keyword, I can easily find the documents but cannot figure out how to update them.
I tried this one, but it doesn't work
db.placements.update({program_id:{$in:[113,107]},
keyword:{$regex:'^[0-9]', $options:'i'}},
{keyword:"+"+$keyword})
It cannot recognize $keyword, I also tried '.keyword', 'keyword', none of them works. Is there any way to reference the document itself like Java does, using 'this', so I can do something like
this.keyword: "+" + this.keyword
You'll have to use the $set operator in the update query to update a specific field. Also, you cannot concatenate string within an update query. One way to do this would be using cursor forEach() in the shell:
db.placements.find({program_id:{$in:[113,107]}, keyword:{$regex:'^[0-9]', $options:'i'}})
.forEach(function(doc){
db.placements.updateOne({_id:doc._id}, {$set:{"keyword":"+" + doc.keyword}})
})
No, you cannot reference a value on the document itself when querying like you can with SQL.
I would suggest querying the document, updating it on your web/app server and then updating the value back to mongodb.
You will also find that your update command above will wipe your entire document leaving only the keyword field. You should use the $set modifier to update a field or set of fields.
db.placements.update(
{
program_id:{$in:[113,107]},
keyword:{$regex:'^[0-9]', $options:'i'}
},
{ $set: {keyword: new_value}})
What is the status of text search with haskell mongodb driver?
There is now 'LIKE' operator in mongo similar to SQL variants, so what is the best way to search a collection or the whole db for a particular text string?
I've read some people referencing external tools but I can also see that some text search was implemented in 2.4 mongo version which is done through command interface.
There should not be any problems doing it from console but how would I do it from haskell driver? I found 'runCommand' function in the driver APIs and it looks like it should be possible to send 'text' command to the server but the signature shows that it returns only one document - not a list of documents. So how is it done correctly?
How would I efficiently search for a word or a sentence in a collection or db so that it returns a list of documents containing the word? Is it possible to do without external tools using mongo 'text search' feature? SHould it be done in the application level?
Thanks.
The result type already contains the list of documents (that contain the searched text). Unfortunately, I could not test the query on my running database, but I have used runCommand to run an aggregation (before it was implemented for the haskell driver). The result document you get for such an query looks something like this:
{ results: [
{ score : ...,
obj : { ... }
},
...
],
... ,
ok : 1
}
The result document has a field results and its value is a document with fields score and obj. So in the end, you can find each of the matched document behind the obj-field in the list of results.
For more details, you should take a look here.
What I'm trying to do:
Filter a field of a collection that matches a given condition. Instead of returning every item in the field (which is an array of items), I only want to see matched items.
Similar to
select items from test where items.histPrices=[10,12]
It is also similar to what's found on the mongodb website here: http://www.mongodb.org/display/DOCS/Retrieving+a+Subset+of+Fields
Here's what I have been trying:
db.test.save({"name":"record", "items":[{"histPrices":[10,12],"name":"stuff"}]})
db.test.save({"name":"record", "items":[{"histPrices":[10,12],"name":"stuff"},
{"histPrices":[12,13],"name":"stuff"},{"histPrices":[11,14],"name":"stuff"}]})
db.test.find({},{"name":1,"items.histPrices":[10, 12]})
It will return all the objects that have a match for items.histPrices:[10,12], including ALL of the items in items[]. But I don't want the ones that don't match the condition.
From the comments left on Mongodb two years ago, the solution to get only the items with that histPrices[10,12] is to do it with javascript code, namely, loop through the result set and filter out the other items.
I wonder if there's a way to do that with just the query.
Your find query is wrong
db.test.find({},{"name":1,"items.histPrices":[10, 12]})
Your condition statement should be in the first part of the find statement.In your query {} means fetch all documents similar to this sql
select items from test (no where clause)
you have to change your mongodb find to
db.test.find({"items.histPrices":[10, 12]},{"name":1})
make it work
since your items is an array and if you wanted to return only the matching sub item, you have to use positional operator
db.test.find({"items.histPrices":[10, 12]},{"name":1,'items.$':1})
When working with arrays Embedded to the Document, the best approach is the one suggested by Chien-Wei Huang.
I would just add another aggregation, with the $group (in cases the document is very long, you may not want to retrieve all its content, only the array elements) Operator.
Now the command would look like:
db.test.aggregate({$match:{name:"record"}},
{$unwind:"$items"},
{$match {"items.histPrices":[10, 12]}},
{$group: {_id: "$_id",items: {$push: "$items"}}});)
If you are interested to return only one element from the array in each collection, then you should use projection instead
The same kind of issue solved here:
MongoDB Retrieve a subset of an array in a collection by specifying two fields which should match
db.test.aggregate({$unwind:"$items"}, {$match:{"items.histPrices":[10, 12]}})
But I don't know whether the performance would be OK. You have to verify it with your data.
The usage of $unwind
If you want add some filter condition like name="record", just add another $march at first, ex:
db.test.aggregate({$match:{name:"record"}}, {$unwind:"$items"}, {$match:{"items.histPrices":[10, 12]}})
https://jira.mongodb.org/browse/SERVER-828
Get particular element from mongoDB array
MongoDB query to retrieve one array value by a value in the array