How do I get the current validator of a mongo collection? - mongodb

How do I get the current validator of a mongo collection?
Or is there no way, and I just need to overwrite it?

You can get it with the db.getCollectionInfos() method.
Example:
Create a collection in an empty database:
db.createCollection( "contacts",
{
validator: { $or:
[
{ phone: { $type: "string" } },
{ email: { $regex: /#mongodb\.com$/ } },
{ status: { $in: [ "Unknown", "Incomplete" ] } }
]
},
validationAction: "warn"
}
)
{ "ok" : 1 }
Run the command:
db.getCollectionInfos()[0].options.validator
Result:
{
"$or" : [
{
"phone": {
"$type": "string"
}
},
{
"email": {
"$regex": /#mongodb\.com$/
}
},
{
"status": {
"$in": [
"Unknown",
"Incomplete"
]
}
}
]
}
The validator is found as an object in the options object.

Related

Mongo Db Query: Update nested collection json property using switch/case or if/else condition

I am using mongo db v4.4.
I am trying to update property value using switch case conditional statement but getting error like..
The dollar ($) prefixed field '$switch' in
'template.0.children.2.isApplicable.$switch' is not valid for storage
Collection Json:
{
"_id": "61b6e8e9cee06e45b48af94b",
"countryCode": "uk",
"template": [
{
"children": [
{
"propertyName": "middle",
"isApplicable": true
}
]
}
]
}
Query:
db.getCollection('mytestcollection').updateMany({
"template.children": {
"$elemMatch": {
"propertyName": "middle"
}
}
}, {
"$set": {
"template.0.children.$[level1].isApplicable": {
$switch: {
branches: [{
case: {
countryCode: {
$in: ['uk']
}
},
then: false
}
],
default: true
}
}
}
},
{
"arrayFilters": [{
"level1.propertyName": "middle"
}]
});
How to solve above error and update property based on switch case/if else condition.

MongoDB $elemsMatch in practice

These are my documents:
[
{
uuid: 1,
emailNotifications: [
{
targetEmailAddress: "w#w.pl"
},
{
targetEmailAddress: "w2#w.pl"
}
]
},
{
uuid: 2,
emailNotifications: [
{
targetEmailAddress: "xxxw#w.pl"
},
{
targetEmailAddress: "xxxw2#w.pl"
},
]
},
]
I want query those with emailNotifications.targetEmailAddress equals to "w#w.pl":
db.collection.find({
emailNotifications: {
$elemMatch: {
targetEmailAddress: "w#wp.pl"
}
}
})
but it finds nothing. Where is the error?
Your value of targetEmailAdress in the query is wrong. You don't have w#wp.pl in your documents.

Query datevalue of a inner Array element

Need help with some MongoDB query:
The document I have is below and I am trying to search based on 2 conditions
The meta.tags.code = "ABC"
Its LastSyncDateTime should
meta.extension.value == "" (OR)
the meta.extension.value is less than meta.lastUpdated
Data :
{
"meta" : {
"extension" : [
{
"url" : "LastSyncDateTime",
"value" : "20190206-00:49:25.694"
},
{
"url" : "RetryCount",
"value" : "0"
}
],
"lastUpdate" : "20190207-01:21:41.095",
"tags" : [
{
"code" : "ABC",
"system" : "type"
},
{
"code" : "XYZ",
"system" : "SourceSystem"
}
]
}
}
Query:
db.proc_patients_service.find({
"meta.tags.code": "ABC",
$or: [{
"meta.extension.value": ""
}, {
$expr: { "$lt": [{ "mgfunc": "ISODate", "params": [{ "$arrayElemAt": ["$meta.extension.value", 0] }] }, { "mgfunc": "ISODate", "params": ["$meta.lastUpdate"] }] }
}]
})
But it is only fetching ABC Patients whose LastSyncDateTime is empty and ignores the other condition.
Using MongoDB Aggregation, I have converted your string to date with operator $dateFromString and then compare the value as per your criteria.
db.proc_patients_service.aggregate([
{ $match: { "meta.tags.code": "ABC", } },
{ $unwind: "$meta.extension" },
{
$project: {
'meta.tags': '$meta.tags',
'meta.lastUpdate': { '$dateFromString': { 'dateString': '$meta.lastUpdate', format: "%Y%m%d-%H:%M:%S.%L" } },
'meta.extension.url': '$meta.extension.url',
'meta.extension.value': {
$cond: {
if: { $ne: ["$meta.extension.value", "0"] }, then: { '$dateFromString': { 'dateString': '$meta.extension.value', format: "%Y%m%d-%H:%M:%S.%L" } }, else: 0
}
}
}
},
{
$match: {
$or: [
{ "meta.extension.value": 0 },
{ $expr: { $lt: ["$meta.extension.value", "$meta.lastUpdate"] } }
]
}
},
{
$group: { _id: '_id', 'extension': { $push: '$meta.extension' }, "lastUpdate": { $first: '$meta.lastUpdate' }, 'tags': { $first: '$meta.tags' } }
},
{
$project: { meta: { 'extension': '$extension', lastUpdate: '$lastUpdate', 'tags': '$tags' } }
}
])

Use of validator in collection defined in Mongo

Basically, I am new to MongoDB and learning from documents. I wanted to use validator, validationLevel, validationAction while defining a collection in MongoDB. So I can get an error if validated data is not inserted or updated. I have followed this document for reference. However, I got success in defining collection but when I add the wrong record it doesn't give me error like it is mentioned in documents. Everytime new record is getting inserted. Can you guys please help me in this whats wrong with my code.
I am using the following command to create a collection
db.createCollection( "contacts",
{
validator: { $and:
[
{ phone: { $type: "string" } },
{ email: { $regex: /#mongodb\.com$/ } },
{ status: { $in: [ "Unknown", "Incomplete" ] } }
],
validationAction: "error"
}
}
)
I have also used the same command with validationLevel to strict like below but it also didn't work out.
db.createCollection( "contacts",
{
validator: { $and:
[
{ phone: { $type: "string" } },
{ email: { $regex: /#mongodb\.com$/ } },
{ status: { $in: [ "Unknown", "Incomplete" ] } }
],
validationAction: "error",
validationLevel: "strict"
}
}
)
A command I used to insert record is as below
db.contacts.insert( { name: "Amanda", status: "Updated" } )
Below is the expected output as per the document.
WriteResult({
"nInserted" : 0,
"writeError" : {
"code" : 121,
"errmsg" : "Document failed validation"
}
})
But I end up getting success output as below
WriteResult({ "nInserted" : 1 })
I guess you validation rule is not applied to the collection. You can check for the same using
getCollectionInfos({name:'constacts'})
here is the link.
Error is in the validationAction and validationLevel.
use this
db.createCollection( "contacts", { validator:
{ $and:
[
{ phone: { $type: "string" } },
{ email: { $regex: /#mongodb\.com$/ } },
{ status: { $in: [ "Unknown", "Incomplete" ] } }
]
},
validationLevel : "strict",
validationAction : "error"
}
)
insted of
db.createCollection( "contacts",
{
validator: { $and:
[
{ phone: { $type: "string" } },
{ email: { $regex: /#mongodb\.com$/ } },
{ status: { $in: [ "Unknown", "Incomplete" ] } }
],
validationAction: "error",
validationLevel: "strict"
}
}
)
Quote from documentation:
You cannot specify a validator for collections in the admin, local,
and config databases. You cannot specify a validator for system.*
collections.
https://docs.mongodb.com/v3.2/reference/method/db.createCollection/

correctly grouping documents in aggregate pipeline in order to find setintersection

say I have these two documents:
{
"_id":"sampleA",
"value":{
"data":[
{
"thing":"A"
},
{
"thing":"B"
},
{
"thing":"C"
},
{
"thing":"D"
},
{
"thing":"E"
}
]
}
}
{
"_id":"sampleB",
"value":{
"data":[
{
"thing":"C"
},
{
"thing":"D"
},
{
"thing":"E"
},
{
"thing":"F"
}
]
}
}
and I want to group them into one document, retaining the label of "sampleA" or "sampleB" such as
{
"_id": null,
"sampleA": [
{
"thing": "A"
},
{
"thing": "B"
},
{
"thing": "C"
},
{
"thing": "D"
},
{
"thing": "E"
}
],
"sampleB": [
{
"thing": "C"
},
{
"thing": "D"
},
{
"thing": "E"
},
{
"thing": "F"
}
]
}
So that way I can use the set intersection operator. How do I go about doing this? I tried:
db.testz.aggregate(
[{
$match: {
_id: {
$in: ["sampleA", "sampleB"]
}
}
}, {
'$group': {
_id: null,
a: {
$push: "$value"
}
}
}]
);
which gives me
{
"_id": null,
"a": [
{
"data": [
{
"thing": "A"
},
{
"thing": "B"
},
{
"thing": "C"
},
{
"thing": "D"
},
{
"thing": "E"
}
]
},
{
"data": [
{
"thing": "C"
},
{
"thing": "D"
},
{
"thing": "E"
},
{
"thing": "F"
}
]
}
]
}
Presumably I could then use the set intersection operator if I could index the items in a?
db.testz.aggregate(
[{
$match: {
_id: {
$in: ["sampleA", "sampleB"]
}
}
}, {
'$group': {
_id: null,
a: {
$push: "$value"
}
}
}, {
'$project': {
int: {
$setIntersection: ["$a.0", "$a.1"]
}
}
}]
);
^^ obviously this last step here doesn't work, but I am trying to illustrate the point.
I think the only way to do this presently (MongoDB 2.6) is to unwind the arrays and then recollect in a set:
> db.testz.aggregate([
{ "$match" : { "_id" : { "$in" : ["sampleA", "sampleB"] } } },
{ "$unwind" : "$value.data" },
{ "$group" : { "_id" : 0, "intersection" : { "$addToSet" : "$value.data" } } }
])
It's not an efficient way to do it, but it gets the job done. I was probing you for more specific info to see if there was some way to avoid this answer :(