mongodb get _id as string in find query
MongoDB 4.0 adds the $convert
aggregation operator and the $toString
alias which allows you to do exactly that:
db.getCollection('example').aggregate([
{ "$match": { "example":1 } },
{ "$project": { "_id": { "$toString": "$_id" } } }
])
A main usage would most likely be though to use the _id
value as a "key" in a document.
db.getCollection('example').insertOne({ "a": 1, "b": 2 })
db.getCollection('example').aggregate([
{ "$replaceRoot": {
"newRoot": {
"$arrayToObject": [
[{
"k": { "$toString": "$_id" },
"v": {
"$arrayToObject": {
"$filter": {
"input": { "$objectToArray": "$$ROOT" },
"cond": { "$ne": ["$$this.k", "_id"] }
}
}
}
}]
]
}
}}
])
Which would return:
{
"5b06973e7f859c325db150fd" : { "a" : 1, "b" : 2 }
}
Which clearly shows the string, as does the other example.
Generally though there is usually a way to do "transforms" on the cursor as documents are returned from the server. This is usually a good thing since an ObjectId
is a 12-byte binary representation as opposed to a 24 character hex "string" which takes a lot more space.
The shell has a .map()
method
db.getCollection('example').find().map(d => Object.assign(d, { _id: d._id.valueOf() }) )
And NodeJS has a Cursor.map()
which can do much the same thing:
let cursor = db.collection('example').find()
.map(( _id, ...d }) => ({ _id: _id.toString(), ...d }));
while ( await cursor.hasNext() ) {
let doc = cursor.next();
// do something
})
And the same method exists in other drivers as well ( just not PHP ), or you can just iterate the cursor and transform the content as is more likely the best thing to do.
In fact, whole cursor results can be reduced into a single object with great ease by simply adding to any cursor returning statement, when working in the shell
.toArray().reduce((o,e) => {
var _id = e._id;
delete e._id;
return Object.assign(o, { [_id]: e })
},{ })
Or for full ES6 JavaScript supporting environments like nodejs:
.toArray().reduce((o,({ _id, ...e })) => ({ ...o, [_id]: e }),{ })
Really simple stuff without the complexity of what needs to process in the aggregation framework. And very possible in any language by much the same means.
If i have a mongo document id as a string how do I query for it as an _id?
Do you mean you have the 24 hex digit string of an ObjectId?
Assuming that's what you mean, most drivers have a way to take a string and convert it to an ObjectId. In JavaScript that's:
.find({_id:new ObjectId("4f91bfcfaa7c5687a0c686d4")})
Updated to be a bit more useful for the node-native driver (from the documentation at https://github.com/christkv/node-mongodb-native):
// Get the objectID type
var ObjectID = require('mongodb').ObjectID;
var idString = '4e4e1638c85e808431000003';
collection.findOne({_id: new ObjectID(idString)}, console.log) // ok
collection.findOne({_id: idString}, console.log) // wrong! callback gets undefined
How do I search for an object by its ObjectId in the mongo console?
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 }
Get Data from another collection (string - ObjectId)
There is matching error in the $lookup
--> $pipeline
--> $match
.
It should be:
$match: {
$expr: {
$eq: [
"$_id",
"$$searchId"
]
}
}
From the provided documents, members
to churchies
relationship will be 1 to many. Hence, when you join members
with churchies
via $lookup
, the output church
will be an array with only one churchies
document.
Aggregation pipelines:
$lookup
- Joinmembers
collection (by$$searchId
) withchurchies
(by_id
).$unwind
- Deconstructchurch
array field to multiple documents.$project
- Decorate output document.$sort
- Sort bychurch
andname
ascending.
db.members.aggregate([
{
"$lookup": {
"from": "churchies",
"let": {
searchId: {
"$toObjectId": "$church"
}
},
"pipeline": [
{
$match: {
$expr: {
$eq: [
"$_id",
"$$searchId"
]
}
}
},
{
$project: {
name: 1
}
}
],
"as": "church"
}
},
{
"$unwind": "$church"
},
{
$project: {
_id: 1,
church: "$church.name",
name: 1
}
},
{
"$sort": {
"church": 1,
"name": 1
}
}
])
Sample Mongo Playground
MongoDB: Query ObjectId via Substring
You can not
query with a regex expression operator against a field that contains ObjectId's.
I suggest providing your own unique string as _id then you can use a regex
the expression for querying.
Example:
// This will add a tempUserId property to each document
Model.aggregate([
{
$addFields: {
tempUserId: { $toString: '$_id' },
}
},
{
$match: {
tempUserId: { $regex: '62a0ed7', $options: "i" }
}
}
]);
A faster solution is that you can also add a pre create hook or whatever to save an id (other than the _id) containing the value of the ObjectId (_id) as a string and you can make a text index on it and do search instead of regex.
Related Topics
Strip HTML Tags and Its Contents
Jquery UI Saving Sortable List
How to Add a PHP Simplexmlelement to Another Simplexmlelement
Cannot Initialize Mbstring with PHP 7
Fatal Error: Uncaught Argumentcounterror: Too Few Arguments to Function
In PHP, Is There Any Harm in Running Session_Start() Multiple Times
Warning Problem: Expects Parameter 1 to Be MySQLi_Result
How to Get a PHP Value from an HTML Form
How to Insert Multiple Rows in PHP Pdo MySQL
How to Detect Ambiguous and Invalid Datetime in PHP
How to 'JSON_Encode()' Keys from PHP Array
Saving Div Contents or Canvas as Image
PHP - Fastest Way to Check Presence of Text in Many Domains (Above 1000)
Troubleshooting "Unexpected T_Echo" in Ternary Operator Statement
SQL Server Error 1934 Occurs on Insert to Table with Computed Column PHP/Pdo