How do you query a Mongo db for rows containing a column with a specific type? - mongodb

I have a collection that has ended up with a column containing an updated timestamp, sometimes as a text field, sometimes as a date field. I am looking for the syntax to execute a query to find all rows that contain that field as a date type.

You can use $type with $not
Checking the not scenario. If type is not of string, then consider that doc.
playground
db.collection.find({
"key": {
$not: {
$type: "string"
}
}
})

Related

MongoDB Dates in Date and String format for the same column

I have a collection where the same column has Date and String format dates for different records, with the same ISO pattern like 2021-04-22T14:10:48.751779Z.
And I need to build a unified query for search, with such =, >, < options for search.
The second problem is an input search query has a different pattern ("2021-04-22")
So the question is:
can I write some kind of transformation of existing table data before the search, for example from Date to String, or in case I have a string value this transformation would not cause any exception.
In this case, I would be able to perform a search by $eq, $lt, $gt, and $regex query options.
I`m not considering casting strings to dates even if this is possible because my input did not have "14:10:48.751779Z" this part of the date and query would not find anything because of dates would not match. For this case, $regex looks like the only solution.
Or your any other suggestions would be considered.
Current query which not satisfies case when DB column is String type:
{
"aggregate":"collection_name",
"pipeline":[
{
"$match":{
"$and":[
{
"some_column":{
"$eq":"some_value"
}
},
{
"date_column_with_string_or_date_type":{
"$gt":{
"$date":"1980-01-01T00:00:00Z"
}
}
}
]
}
},
{
"$project":{
"_id":1
}
}
]
}
Solved by using $expr and $toString
This works with Date And String types of "date_column"
$match: {
$expr: {
$gt : [
{ $toString:"$date_column" },
"2021-04-22"
]
}
}
operator:

Mongo Atlas Search Index numeric field exact match search

We are using MongoDB Atlas Search Indexes to query and filter the documents list. consider below document.
{_id:5sfgdfgf2c46e0fb00019bdecc,
user_id:4996,
bom_number:"112",
name:"test"}
Created default Index:
{
"mappings": {
"dynamic": false,
"fields": {
"user_id": {
"type": "string"
}
}
}
}
Query:
{
text: {
query: ["4996","3888"],
path: 'user_id'
}
}
It is not returning any documents. Can anyone please guide. I know we actually stored user_id as numeric form and I tried indexing and querying the field as String. Please help me out and suggest correct way of querying mongo atlas numeric field with multiple values.
$search is what you need to use to query using the index that you have created and you also need to mention the name of the index in the query.
The below draft might help you:
$search:{
{
index: "index_name_created_from_atlas_search",
text: {
query: "<actual data you need to search>",
path: "<field_name>"
}
}
}
And based on your example, if you want to have multiple conditions with the search, you can refer to official documentation here of all sorts of multiple conditions you can integrate with the $search aggregation using the compound operator.

How to find in MongoDB by last 4 chars in ObjectID?

I don't want to expose the full object ID to the client, instead I want to show him only a short of the last 4 chars of the actual object ID of an entity in the collection.
For example: ObjectId("5fcca5d997239a74da0d67a9") will become just 67a9
So it will be much easier to "talk" with ids of documents instead of the full object it.
Then I need to find the document in the DB using only the 67a9.
Is this possible and how?
According to this issue in Jira the resolution is "Won't fix".
ObjectId is not a String, is another object, so $regex is no possible.
Check this example where $regex works ok when _id is an String but not an ObjectId.
So one possible option is duplicate every field _id in another field called id or whatever where the id is in String format.
Then, you can do this query:
db.collection.find({
"_id": {
"$regex": "67a9$"
}
})
Example here where I've added more _id fields that not match the pattern
As pointed out, regex won't work on an ObjectId. But there is an easy workaround. Just use aggregation to first convert your ObjectId into a string and then match it.
db.collection.aggregate([
{
$addFields: {
tempId: { $toString: '$_id' },
}
},
{
$match: {
tempId: { $regex: "67a9"}
}
}
])
Obviously not a great solution to use on very large collections.

Delete documents where value is not an array

It seems that mongodb allows the same syntax for deleting documents where the value is a single value, and whenever the value is present in a collection:
This
db.SomeCollection.deleteMany({UserId: 12345});
Can affect both {UserId: 12345} and {UserId: [12345, 67895, 87897]}.
I understand that this schema isn't ideal; we are using a singular UserId prop to denote both a single id int, and an array of ints. However, I've inherited a database that makes use of mongodb's dynamic nature, if you catch my drift.
What is the safest way to execute a deleteMany query, specifying I only want to delete documents where the value is a single integer?
You can use $type operator to check field type but it's not so obvious in this case. You can't check if UserId is of type double because MongoDB will indicate that array of doubles is a double as well (more here). So you need to invert your logic and check if documents you're trying to remove are not an array (type 4):
db.SomeCollection.deleteMany({ $and: [ { UserId: 12345 }, { UserId: { $not: { $type: 4 } } } ] })

Find non-ISODate records in MongoDb

I have a Mongo collection that stored a date field as a string. I ran the query below to convert this field into an ISODate, but it failed. However, there are quite a few records that now show as an ISODate.
How do I query to find all documents that are an ISODate format and all documents that are still a string?
db.TestCollection.find({}).forEach(function(doc) {
doc.LastUpdated = new Date(doc.LastUpdated );
db.TestCollection.save(doc);
});
The original question has been answered, but the follow up question is: Is there a way to aggregate the type of data present in the column? I would like to return a count of each type of data in the column. I have seen type string and type date, but want to verify there isn't any other data types.
Here's roughly what I have tried:
db.TestCollection.aggregate([{
$project: {
LastUpdated : { $type: "$LastUpdated " }
}
}])