Retrieving only the relevant part of a stored document - mongodb

I'm a newbie with MongoDB, and am trying to store user activity performed on a site. My data is currently structured as:
{ "_id" : ObjectId("4decfb0fc7c6ff7ff77d615e"),
"activity" : [
{
"action" : "added",
"item_name" : "iPhone",
"item_id" : 6140,
},
{
"action" : "added",
"item_name" : "iPad",
"item_id" : 7220,
}
],
"name" : "Smith,
"user_id" : 2
}
If I want to retrieve, for example, all the activity concerning item_id 7220, I would use a query like:
db.find( { "activity.item_id" : 7220 } );
However, this seems to return the entire document, including the record for item 6140.
Can anyone suggest how this might be done correctly? I'm not sure if it's a problem with my query, or with the structure of the data itself.
Many thanks.

You have to wait the following dev: https://jira.mongodb.org/browse/SERVER-828
You can use $slice only if you know insertion order and position of your element.
Standard queries on MongoDb always return all document.
(question also available here: MongoDB query to return only embedded document)

Related

How to reduce execution time in this mongo db find query?

document sample data followed like this,
{
"_id" : ObjectId("62317ae9d007af22f984c0b5"),
"productCategoryName" : "Product category 1",
"productCategoryDescription" : "Description about product category 1",
"productCategoryIcon" : "abcd.svg",
"status" : true,
"productCategoryUnits" : [
{
"unitId" : ObjectId("61fa5c1273a4aae8d89e13c9"),
"unitName" : "kilogram",
"unitSymbol" : "kg",
"_id" : ObjectId("622715a33c8239255df084e4")
}
],
"productCategorySizes" : [
{
"unitId" : ObjectId("61fa5c1273a4aae8d89e13c9"),
"unitName" : "kilogram",
"unitSize" : 10,
"unitSymbol" : "kg",
"_id" : ObjectId("622715a33c8239255df084e3")
}
],
"attributes" : [
{
"attributeId" : ObjectId("62136ed38a35a8b4e195ccf4"),
"attributeName" : "Country of Origin",
"attributeOptions" : [],
"isRequired" : true,
"_id" : ObjectId("622715ba3c8239255df084f8")
}
]
}
This collection has been indexed in "_id". without sub-documents execution time is reduced but all document fields are required.
db.getCollection('product_categories').find({})
This collection contains 30000 records and this query takes more than 30 seconds to execute. so how to solve this issue. Anybody ask me a better solution. Thanks.
Indexing and compound indexing will make it use cache instead of scanning document every time you query it. 30.000 documents is nothing to MongoDB, it can handle millions in a second. If these fields are populated in the process that's another heavy operation for the query.
See if your schema is efficiently structured or you're throttling your connection to the server. Other thing to consider is to project only the fields that you require, using aggregation pipeline.
Although the question is not very clear you can follow this article for some best practices.

how to use update query in mongoDb?

I have few documents in user Collection like below .I need to update ancestors field alone,Need to add few more values.
db.users.find()
{
"_id" : ObjectId("5d9fd81f3d598088d2ea5dcc"),
"DOB" : ISODate("1979-05-23T00:00:00Z"),
"userImage" : "sathish_1589780950636.jpeg",
"createdDateTime" : ISODate("2016-02-01T09:43:27Z"),
"modifiedDateTime" : ISODate("2017-04-26T15:57:09Z"),
"status" : "active",
"ancestors" : [
ObjectId("5d9fd81b3d598088d2ea5dc7")
],
"parent" : ObjectId("5d9fd81b3d598088d2ea5dc7")
}
When i tried the below query.
db.users.update({"_id" : ObjectId("5d9fd81f3d598088d2ea5dcc")},{$set:{"ancestors" : [
ObjectId("5f45f9491ff4bd74ec754e3a"),
ObjectId("5d9fd8203d598088d2ea5dcd"),
ObjectId("5d9fd8723d598088d2ea5e43")
]}})
It just replace the old one and completely adding the new one.
I need the result to be like this .old data should also remain and new one should be added.
"ancestors" : [
ObjectId("5f45f9491ff4bd74ec754e3a"),
ObjectId("5d9fd8203d598088d2ea5dcd"),
ObjectId("5d9fd81b3d598088d2ea5dc7"),
ObjectId("5d9fd8723d598088d2ea5e43")
]
This update query should be done in all documents in that collection. the above mentioned 3 values to be added in all documents, instead of find and update, I should be doing bulk updated
I think you can run the following:
db.users.updateOne({"_id" : ObjectId("5d9fd81f3d598088d2ea5dcc")},{$addToSet:{"ancestors" :{ $each: [
ObjectId("5f45f9491ff4bd74ec754e3a"),
ObjectId("5d9fd8203d598088d2ea5dcd"),
ObjectId("5d9fd8723d598088d2ea5e43")
]}}})
ref: https://docs.mongodb.com/manual/reference/operator/update/each/
You can use mongodb method $push
db.users.update({"_id" : ObjectId("5d9fd81f3d598088d2ea5dcc")},
{ $push: {ancestors:ObjectId("5f45f9491ff4bd74ec754e3a") } })
[check doc][1]
[1]: https://docs.mongodb.com/manual/reference/operator/update/push/

Adding to a double-nested array in MongoDB

I have a double nested array in my MongoDB schema and I'm trying to add an entirely new array element to a second-level nested array using $push. I'm getting the error cannot use the part (...) to traverse the element
A documents have the following structure
{
"_id" : ObjectId("5d8e37eb46c064790a28a467"),
"org-name" : "Manchester University NHS Foundation Trust",
"domain" : "mft.nhs.uk",
"subdomains" : [ {
"name" : "careers.mft.nhs.uk",
"firstSeen" : "2017-10-06 11:32:00",
"history" : [
{
"a_rr" : "80.244.185.184",
"timestamp" : ISODate("2019-09-27T17:24:57.148Z"),
"asn" : 61323,
"asn_org" : "Ukfast.net Limited",
"city" : null,
"country" : "United Kingdom",
"shodan" : {
"ports" : [
{
"port" : 443,
"versions" : [
"TLSv1",
"-SSLv2",
"-SSLv3",
"TLSv1.1",
"TLSv1.2",
"-TLSv1.3"
],
"cpe" : "cpe:/a:apache:http_server:2.4.18",
"product" : "Apache httpd"
}
],
"timestamp" : ISODate("2019-09-27T17:24:58.538Z")
}
}
]
}
]
}
What I'm attempting to do is refresh the details held in the history array and add another entire array entry to represent the most recently collected data for the subdomain.name
The net result is that I will have multiple entries in the history array, each one timestamped the the date that the data was refreshed. That way I have a historical record of changes to any of the data held.
I've read that I can't use $push on a double-nested array but the other advice about using arrayfilters all appear to be related to updating an entry in an array rather than simply appending an entirely new document - unless I'm missing something!
I'm using PyMongo and would simply like to build a new dictionary containing all of the data elements and simply append it to the history.
Thanks!
Straightforward in pymongo:
record = db.mycollection.find_one()
record['subdomains'][0]['history'].append({'another': 'record'})
db.mycollection.replace_one({'_id': record['_id']}, record)

MongoDB : best way to storing key value data

I have to migrate from MySQL to MongoDB , and i beginner in MongoDB, what is the best way to storing below data in MongoDB ?
should i create a document for each row?
should i save all row in a one document?
Which one is valid way in MongoDB?
{
"_id" : ObjectId("5659d56fef6c702fbc45cc1b")
"key" : "setting_update_id"
"value" : "1"
"extra" :
[
//some data
]
}
OR
{
"_id" : ObjectId("5659d56fef6c702fbc45cc1b")
"setting_update_id" : "1"
"extra" :
[
//some data
]
}
Ali,
As a beginner you would want to read the docs here. Each collection can be thought of roughly as a table in a relational database. And each document can be thought of as a row in the database. So each column of your table would be the keys of your document.
I would design it closer to the first one.
{
"_id" : ObjectId("5659d56fef6c702fbc45cc1b")
"key" : "setting_update_id"
"value" : "1"
"params" :
{
"extra" : "hello",
"foo" : "bar"
}
}

I have big database on mongodb and can't find and use my info

This my code:
db.test.find() {
"_id" : ObjectId("4d3ed089fb60ab534684b7e9"),
"title" : "Sir",
"name" : {
"_id" : ObjectId("4d3ed089fb60ab534684b7ff"),
"first_name" : "Farid"
},
"addresses" : [
{
"city" : "Baku",
"country" : "Azerbaijan"
},{
"city" : "Susha",
"country" : "Azerbaijan"
},{
"city" : "Istanbul",
"country" : "Turkey"
}
]
}
I want get output only all city. Or I want get output only all country. How can i do it?
I'm not 100% about your code example, because if your 'find' by ID there's no need to search by anything else... but I wonder whether the following can help:
db.test.insert({name:'farid', addresses:[
{"city":"Baku", "country":"Azerbaijan"},
{"city":"Susha", "country":"Azerbaijan"},
{"city" : "Istanbul","country" : "Turkey"}
]});
db.test.insert({name:'elena', addresses:[
{"city" : "Ankara","country" : "Turkey"},
{"city":"Baku", "country":"Azerbaijan"}
]});
Then the following will show all countries:
db.test.aggregate(
{$unwind: "$addresses"},
{$group: {_id:"$country", countries:{$addToSet:"$addresses.country"}}}
);
result will be
{ "result" : [
{ "_id" : null,
"countries" : [ "Turkey", "Azerbaijan"]
}
],
"ok" : 1
}
Maybe there are other ways, but that's one I know.
With 'cities' you might want to take more care (because I know cities with the same name in different countries...).
Based on your question, there may be two underlying issues here:
First, it looks like you are trying to query a Collection called "test". Often times, "test" is the name of an actual database you are using. My concern, then, is that you are trying to query the database "test" to find any collections that have the key "city" or "country" on any of the internal documents. If this is the case, what you actually need to do is identify all of the collections in your database, and search them individually to see if any of these collections contain documents that include the keys you are looking for.
(For more information on how the db.collection.find() method works, check the MongoDB documentation here: http://docs.mongodb.org/manual/reference/method/db.collection.find/#db.collection.find)
Second, if this is actually what you are trying to do, all you need to for each collection is define a query that only returns the key of the document you are looking for. If you get more than 0 results from the query, you know documents have the "city" key. If they don't return results, you can ignore these collections. One caveat here is if data about "city" is in embedded documents within a collection. If this is the case, you may actually need to have some idea of which embedded documents may contain the key you are looking for.