querying on internals in mongo - mongodb

I have document structure like:
{ "_id": { "$oid" : "51711cd87023380037000001" },
"dayData": "{ "daysdata":{"date":"02-12-2013","week_day":"","month":"","date_day":"","year":"2013"}}"
}
I want to extract document having date = "02-12-2013" in the above. Here i am trying to query on a value which is also a json.
Please let me know how to use mongodb java driver to extract this

Not answer (stackoverflow won't let me comment as I don't have enough points!)
Your string containing json has a syntax error.
There is a single " after "year":"2013"
You may have to fix that 1st.

Related

How to return raw JSON directly from a mongodb query?

In MongoDB (using mongosh or command-line mongo cli), you can query documents, for example using db.mycollection.find({"something":true}) and get the following result:
{
"someDate": ISODate("2022-10-24T17:21:44.980Z"),
"something": true,
"hello": "world"
}
This result, however, is not valid JSON (Due to ISODate). How can I change the query above to make MongoDB return canonical (valid) JSON?
I'm looking for a recursive and generalized way to do this, even for deeply nested documents.
There are a number of existing answers, I'll clarify a few:
Use aggregate to produce the output in JSON format: Playground
db.collection.aggregate([
{
$match: {
something: true
}
},
{
$project: {
_id: 1,
someDate: {
$dateToString: {
format: "%Y-%m-%dT%H:%M:%S:%LZ",
date: "$someDate"
}
},
something: 1,
hello: 1
}
}
])
Loop through your query in your application: (example, node.js)
db.mycollection.find({"something":true}).forEach(function(doc) {
doc.someDate = doc.someDate.toISOString() // or even .toJSON()
})
// Or with await
const records = await db.mycollection.find({"something":true}).map(doc => {
doc.someDate = doc.someDate.toISOString()
return doc
}).toArray()
The details of where you are running this command are very important, can you please share those?
I am guessing that you are probably running this via the (older) mongo utility (as opposed to the newer mongosh). But confirmation of that, and the database version that you are using, would both be helpful. I will retain this assumption for the purposes of this answer.
This result, however, is not valid JSON (Due to ISODate).
The database itself doesn't return some text that has ISODate. In fact, it doesn't return or "speak" JSON at all. Rather, the database communicates via "Binary JSON" or BSON for short. In fact, the "Does MongoDB use BSON or JSON?" section of this page specifically mentions the following:
Firstly, BSON documents may contain Date or Binary objects that are not natively representable in pure JSON.
So when you see things like ISODate() that is the client application wrapping and representing the rich BSON document in a more limited (and text-based) JSON-like form. Importantly, this is often for readability purposes. You should be able to natively pass around and operate on information (documents) returned by the database directly in the application without doing any sort of transformation and without losing rich type information. Additional reading material about BSON is here.
Getting back to the original question, if you want to have the shell print out a valid JSON document than you can do that via additional helpers. In the older mongo utility, a reproduction of the situation described in the question is:
> db.mycollection.findOne({"something": true})
{
"_id" : 1,
"someDate" : ISODate("2022-11-30T14:38:37.711Z"),
"something" : true,
"hello" : "world"
}
The shell itself can understand and operate on ISODate() (and other functions of that nature). If you did want to remove things like ISODate() for some reason, then you can leverage the JSON.stringify() functionality (reformatted with line indents for readability):
> JSON.stringify( db.mycollection.findOne({"something": true}) )
{
"_id":1,
"someDate":"2022-11-30T14:38:37.711Z",
"something":true,
"hello":"world"
}
The newer mongosh shell offers even more utility here:
> EJSON.serialize( db.mycollection.findOne() )
{
_id: 1,
someDate: { '$date': '2022-11-30T14:38:37.711Z' },
something: true,
hello: 'world'
}
Via these EJSON functions, mongosh is attempting to preserve type information when it prints the data in this format. Notice that in the earlier example the date was just represented as a string, but here the shell is using Extended JSON to capture the fact that the type of someDate is a Date.

Cast MongoDB $objects ($oid, $date, $binary...) to Mongoose objects

Well, I have used MongoDB in a while but I don't know how to handle this situation.
The scenario is: I have data inserted in MongoDB. I have exported the data in JSON format, and it is something like:
[
{
"_id": { "$oid": "60ff324f41c4d5b96054390d" },
"field": {
"due_date": { "$date": "2021-11-03T00:09:18.271Z" }
}
}
]
You can see that :
_id is { "$oid": "60ff324f41c4d5b96054390d" } and
date is { "$date": "2021-11-03T00:09:18.271Z" }.
So, the problem is trying to insert in another DB using Mongoose. I want to test some funcionality isolated so I wan't these values in other environment, so I have used insertMany() with the JSON previously exported.
(Maybe there is a more elegant way to import a JSON file but is only for testing purposes)
await model.insertMany(JSON.parse(fs.readFileSync('./data.json').toString()))
But the problem is here: It throws an error because my schema says that _id is an ObjectId and due_date is a Date object but they are actually read as objects: {$oid: ""} and {$date: ""}
ValidationError: model validation failed: _id: Cast to ObjectId failed for value "{ '$oid': '60ff324f41c4d5b96054390d' }" (type Object) at path "_id", field.due_date: Cast to date failed for value "{ '$date': '2021-11-03T00:09:18.271Z' }" (type Object) at path "field.due_date"
So the question is: Is there any way to cast the $oid and $date objects using mongoose while inserting?
Also, I have managed to insert the values using a very ugly script iterating over each value and checking if the object is $oid or $date and modifying the values... but it works.
So the question is not: "Is there a workaround to do this?" but "Is there a way to do it directly with mongoose functions as insertMany and casted automatically?"
Thanks.
The {"$oid": ...} and {"$date":...} constructs are MongoDB extended JSON notation, since JSON does not have any type for Date or ObjectId.
In order to insert those values, you will need to use a JSON parser that knows about this extended format.
One possibility is the json_util that is included with bson.
Or you can use mongoimport to read the JSON file and do the inserts for you.

How to retrieve values of nested objects in a Mongo DB document using java

I have a document like below:
"application" : "test",
"QA1" : {
"url" : "https://google.co.in",
"db" : {
"userName" : "user",
"password" : "pswd"
}
}
I want to retrieve the value "https://google.co.in" by calling the key "url".
While using the below shell command, I am able to retrieve the value as expected.
db.getCollection('Application_Data').findOne({"application":"test"}).QA1.url
But when I convert it to java code, it is throwing me null pointer exception:
cursor = collection.find(Filters.eq("application","test")).iterator();
while (cursor.hasNext()) {
value=cursor.next().get("QA1.url").toString();
break;
}
I also tried with projection like below to get the required values:
cursor = collection.find(Filters.and(Filters.eq("application","test"))).projection(Projections.fields(Projections.include("QA1.url"),Projections.excludeId())).iterator();
while (cursor.hasNext()) {
System.out.println(cursor.next().get("QA1").toString());
}
This is giving me the output as below:
Document{{url=https://google.co.in}}
It is still not giving me the exact value. Appreciate your help on this.
Mongodb Documents are nested. So say, in your example, when you do cursor.next().get("QA1"), you get the Document under "QA1" property.
So the way to achieve what you want is
cursor.next().get("QA1").get("url"). That, with proper error handling (think exceptions).
A better way to do what you want is to use a mapper like spring-data-mongodb that would map the JSON response of mongodb into a java object for you automatically.
You need to use the Document class's getEmbedded method to extract the nested field's value.
while (cursor.hasNext()) {
Document doc = cursor.next();
System.out.println(doc.toJson());
String urlValue = doc.getEmbedded(Arrays.asList("QA1","url"), String.class);
System.out.println(urlValue); // output below
}
The result is as expected - a string: https://google.co.in

Finding an object ID embedded in an array [duplicate]

I've found this question answered for C# and Perl, but not in the native interface. I thought this would work:
db.theColl.find( { _id: ObjectId("4ecbe7f9e8c1c9092c000027") } )
The query returned no results. I found the 4ecbe7f9e8c1c9092c000027 by doing db.theColl.find() and grabbing an ObjectId. There are several thousand objects in that collection.
I've read all the pages that I could find on the mongodb.org website and didn't find it. Is this just a strange thing to do? It seems pretty normal to me.
Not strange at all, people do this all the time. Make sure the collection name is correct (case matters) and that the ObjectId is exact.
Documentation is here
> db.test.insert({x: 1})
> db.test.find() // no criteria
{ "_id" : ObjectId("4ecc05e55dd98a436ddcc47c"), "x" : 1 }
> db.test.find({"_id" : ObjectId("4ecc05e55dd98a436ddcc47c")}) // explicit
{ "_id" : ObjectId("4ecc05e55dd98a436ddcc47c"), "x" : 1 }
> db.test.find(ObjectId("4ecc05e55dd98a436ddcc47c")) // shortcut
{ "_id" : ObjectId("4ecc05e55dd98a436ddcc47c"), "x" : 1 }
If you're using Node.js:
var ObjectId = require('mongodb').ObjectId;
var id = req.params.gonderi_id;
var o_id = new ObjectId(id);
db.test.find({_id:o_id})
Edit: corrected to new ObjectId(id), not new ObjectID(id)
Even easier, especially with tab completion:
db.test.find(ObjectId('4ecc05e55dd98a436ddcc47c'))
Edit: also works with the findOne command for prettier output.
You Have missed to insert Double Quotes.
The Exact Query is
db.theColl.find( { "_id": ObjectId("4ecbe7f9e8c1c9092c000027") } )
If you are working on the mongo shell, Please refer this : Answer from Tyler Brock
I wrote the answer if you are using mongodb using node.js
You don't need to convert the id into an ObjectId. Just use :
db.collection.findById('4ecbe7f9e8c1c9092c000027');
this collection method will automatically convert id into ObjectId.
On the other hand :
db.collection.findOne({"_id":'4ecbe7f9e8c1c9092c000027'}) doesn't work as expected. You've manually convert id into ObjectId.
That can be done like this :
let id = '58c85d1b7932a14c7a0a320d';
let o_id = new ObjectId(id); // id as a string is passed
db.collection.findOne({"_id":o_id});
I think you better write something like this:
db.getCollection('Blog').find({"_id":ObjectId("58f6724e97990e9de4f17c23")})
Once you opened the mongo CLI, connected and authorized on the right database.
The following example shows how to find the document with the _id=568c28fffc4be30d44d0398e from a collection called “products”:
db.products.find({"_id": ObjectId("568c28fffc4be30d44d0398e")})
I just had this issue and was doing exactly as was documented and it still was not working.
Look at your error message and make sure you do not have any special characters copied in. I was getting the error
SyntaxError: illegal character #(shell):1:43
When I went to character 43 it was just the start of my object ID, after the open quotes, exactly as I pasted it in. I put my cursor there and hit backspace nothing appeared to happen when it should have removed the open quote. I hit backspace again and it removed the open quote, then I put the quote back in and executed the query and it worked, despite looking exactly the same.
I was doing development in WebMatrix and copied the object id from the console. Whenever you copy from the console in WebMatrix you're likely to pick up some invisible characters that will cause errors.
In MongoDB Stitch functions it can be done using BSON like below:
Use the ObjectId helper in the BSON utility package for this purpose like in the follwing example:
var id = "5bb9e9f84186b222c8901149";
BSON.ObjectId(id);
For Pythonists:
import pymongo
from bson.objectid import ObjectId
...
for row in collectionName.find(
{"_id" : ObjectId("63ae807ec4270c7a0b0f2c4f")}):
print(row)
To use Objectid method you don't need to import it. It is already on the mongodb object.
var ObjectId = new db.ObjectId('58c85d1b7932a14c7a0a320d');
db.yourCollection.findOne({ _id: ObjectId }, function (err, info) {
console.log(info)
});
Simply do:
db.getCollection('test').find('4ecbe7f9e8c1c9092c000027');

How to remove _id from MongoDB results?

I am inserting json file into Mongodb(with Scala/Play framework) and the same getting/downloading it into my view page for some other requirement, but this time it is coming with one "_id" parameter in the json file.
But I need only my actual json file only that is not having any any "_id" parameter. I have read the Mongodb tutorial, that by default storing it with one _id for any collection document.
Please let me know that how can I get or is there any chance to get my actual json file without any _id in MongoDB.
this is the json result which is storing in database(I don't need that "_id" parameter)
{
"testjson": [{
"key01": "value1",
"key02": "value02",
"key03": "value03"
}],
"_id": 1
}
If you have a look at ReactiveMongo dev guide and to its API, you can see it support projection in a similar way as the MongoDB shell.
Then you can understand that you can do
collection.find(selector = BSONDocument(), projection = BSONDocument("_id" -> 0))
Or, as you are using JSON serialization:
collection.find(selector = Json.obj(), projection = Json.obj("_id" -> 0))
You can use this query in the shell:
db.testtable.find({},{"_id" : false})
Here we are telling mongoDB not to return _id from the collection.
You can also use 0 instead of false, like this:
db.testtable.find({},{"_id" : 0})
for scala you need to convert it in as per the driver syntax.