How to query multi value in mogoDB - json

I am a beginner to use mogoDB (json/noSQL). Please help me using the query in mogoDB. In SQL i use like :
select * from account where 'status'='active' and
('create_by'= 'USE001' or 'create_by' = 'USE004' or 'create_by' = 'USE035')".
In mogoDB (json/noSQL), How can i do it ??
This is my data structure:
{
"id":"ACC0001",
"create_day":"2020-04-20 16:56:11",
"create_by":"USE001",
"brief_name":"AAAAA",
"status":"active"
},
{
"id":"ACC0002",
"create_day":"2020-04-20 16:56:12",
"create_by":"USE002",
"brief_name":"BBBBB",
"status":"inactive"
},
{
"id":"ACC0003",
"create_day":"2020-04-20 16:56:13",
"create_by":"USE003",
"brief_name":"CCCCC",
"status":"active"
},
{
"id":"ACC0004",
"create_day":"2020-04-20 16:56:14",
"create_by":"USE004",
"brief_name":"DDDDD",
"status":"inactive"
},
{
"id":"ACC9999",
"create_day":"2020-04-20 16:56:15",
"create_by":"USE100",
"brief_name":"FFFFF",
"status":"active"
}

We can translate your query into the following, note my use of the $in operator.
db.account.find({
status: "active",
create_by: { $in: [ "USE001", "USE004", "USE035" ] }
})
You could technically also run this as the query below, however, mongo recommends using $in over $or if you're doing equality checks on the same field. I'm mentioning this since you weren't using IN in your original MySQL query. See: https://docs.mongodb.com/manual/reference/operator/query/or/#or-versus-in
db.account.find({
status: "active",
$or: [
{ create_by: "USE001" },
{ create_by: "USE004" },
{ create_by: "USE035" }
]
})

Related

MongoDB nested array query how to

I am trying to query a document in my MongoDB
Document:
{
_id: '111',
subEntities: [
{
subId: '999',
dateOfStart: '2098-01-01',
dateOfTermination: '2099-12-31'
},
{
subId: '998',
dateOfStart: '2088-01-01',
dateOfTermination: '2089-12-31'
}
]
}
My Query:
{"$and": [
{"subEntities.dateOfStart": {"$lte": "2098-01-02"}},
{"subEntities.dateOfTermination": {"$gte": "2099-12-30"}},
{"subEntities.subId": {"$in": ["998"]}}
]}
As you can see, I am trying to apply a date value and an ID to the subentities.
The date value should be between dateOfStart and dateOfTermination.
The query returns a match, although the date value only matches the first subentity and the ID query matches the second subquery.
How can I make it so that there is only one match when both queries match the same subentity?
Can I aggregate the subentities?
Thanks a lot!
When you query arrays Mongo by default "flattens" them, which means each condition of the query get's executed independently.
You want to be using $elemMatch, this allows you to query full objects from within an array, like so:
db.collection.find({
subEntities: {
$elemMatch: {
dateOfStart: {
"$lte": "2098-01-02"
},
dateOfTermination: {
"$gte": "2099-12-30"
},
subId: {
"$in": [
"998"
]
}
}
}
})
Mongo Playground
If you want to filter dates between dateOfStart and dateOfTermination you should invert the $gte and $lte conditions:
{
"$and": [
{ "subEntities.dateOfStart": { "$gte": "2098-01-02" } },
{ "subEntities.dateOfTermination": { "$lte": "2099-12-30" } },
{ "subEntities.subId": { "$in": ["998"] } }
]
}

MongoDB Split document field into two fields

I have a MongoDB document with over 2.8m documents of common passwords (hashed in SHA1) and their popularity.
Currently I've imported the documents with the following schema
{"_id":"5ded1a559015155eb8295f48","password":"20EABE5D64B0E216796E834F52D61FD0B70332FC:2512537"}
Although I'd like to split this so I can have the popularity value and it would look something like this
{"_id":"5ded1a559015155eb8295f48","password":"20EABE5D64B0E216796E834F52D61FD0B70332FC","popularity":2512537}
Question is im unsure how I can split the password into two password, popularity using : to split the string
You can use Aggregation Framework to split current password into two fields. You need to start with $indexOfBytes to get the position of : and then you need $substr to create new fields based on evaluated position.
db.collection.aggregate([
{
$addFields: {
colonPos: { $indexOfBytes: ["$password",":"] }
}
},
{
$addFields: {
password: { $substr: [ "$password", 0, "$colonPos" ] },
popularity: { $substr: [ "$password", "$colonPos", { $strLenBytes: "$password" } ] }
}
},
{
$project: {
colonPos: 0
}
}
])
Mongo Playground
As a last step you can use $out which takes all your aggregation results and writes them into new or existing collection.
EDIT: Alternative approach using $split (thank to #matthPen):
db.collection.aggregate([
{
$addFields: {
password: { $arrayElemAt: [ { "$split": [ "$password", ":"] }, 0 ] },
popularity: { $arrayElemAt: [ { "$split": [ "$password", ":"] }, 1 ] }
}
}
])
Mongo Playground

Return selected JSON object from mongo find method

Here is the sample JSON
Sample JSON:
[
{
"_id": "123456789",
"YEAR": "2019",
"VERSION": "2019.Version",
"QUESTION_GROUPS": [
{
"QUESTIONS": [
{
"QUESTION_NAME": "STATE_CODE",
"QUESTION_VALUE": "MH"
},
{
"QUESTION_NAME": "COUNTY_NAME",
"QUESTION_VALUE": "IN"
}
]
},
{
"QUESTIONS": [
{
"QUESTION_NAME": "STATE_CODE",
"QUESTION_VALUE": "UP"
},
{
"QUESTION_NAME": "COUNTY_NAME",
"QUESTION_VALUE": "IN"
}
]
}
]
}
]
Query that am using :
db.collection.find({},
{
"QUESTION_GROUPS.QUESTIONS.QUESTION_NAME": "STATE_CODE"
})
My requirement is retrive all QUESTION_VALUE whose QUESTION_NAME is equals to STATE_CODE.
Thanks in Advance.
If I get you well, What you are trying to do is something like:
db.collection.find(
{
"QUESTION_GROUPS.QUESTIONS.QUESTION_NAME": "STATE_CODE"
},
{
"QUESTION_GROUPS.QUESTIONS.QUESTION_VALUE": 1
})
Attention: you will get ALL the "QUESTION_VALUE" for ANY document which has a QUESTION_GROUPS.QUESTIONS.QUESTION_NAME with that value.
Attention 2: You will get also the _Id. It is by default.
In case you would like to skip those issues, you may need to use Aggregations, and unwind the "QUESTION_GROUPS"-> "QUESTIONS". This way you can skip both the irrelevant results, and the _id field.
It sounds like you want to unwind the arrays and grab only the question values back
Try this
db.collection.aggregate([
{
$unwind: "$QUESTION_GROUPS"
},
{
$unwind: "$QUESTION_GROUPS.QUESTIONS"
},
{
$match: {
"QUESTION_GROUPS.QUESTIONS.QUESTION_NAME": "STATE_CODE"
}
},
{
$project: {
"QUESTION_GROUPS.QUESTIONS.QUESTION_VALUE": 1
}
}
])

How to fetch results from mongodb aggregate with two matching fields

I am trying to get the sum ratings of user admin from this JSON object:
{
"_id": "5a7ef9a0ce8b5c00147c1ef3",
"assessed_by": "admin",
"rating": "Sad",
"assessment_date": "2018-02-10T13:54:53.303Z"
},
{
"_id": "5a7efe6083fec3001465b369",
"assessed_by": "admin",
"rating": "Sad",
"assessment_date": "2018-02-10T14:15:01.485Z"
}
Expected output:
{
"_id" : "admin",
"count" : 2.0
}
I also wanted to sort the assessment_date by range so I used the $and operator but it doesn't seem to work on Node. I have my code here:
const now = moment().utc();
const endDate = moment().utc().subtract(9, 'days');
model.aggregate({
$match: {
$and: [
{rating: "Sad"},
{assessment_date: {$lte: now}},
{assessment_date: {$gte: endDate}}
]
}
}, { $group:
{ _id: "admin",
count: {
$sum: 1 }
}
}, function(err, results){
console.log(results)
})
Mongo syntax seemed to work on Robomongo, but it doesn't work when trying on Node.
Your aggregation pipeline stages need to be in an array.
model.aggregate( [ { <stage> }, ... ] )

MongoDB: Search for a string in a collection and return only matched collection items

I have the following json saved in the mongoDB:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"ID": "1753242",
"TYPE": "8003"
}
},
{
"type": "Feature",
"properties": {
"ID": "4823034",
"TYPE": "7005"
}
}
]
}
When i want to search for a specific TYPE, I can do it like this:
db.geo.find({"features.properties.TYPE":"8003"})
My problem is, that this query returns the whole json and not just elements with the TYPE "8003".
Does anybody know, how to retrieve just elements with the TYPE "8003" by query?
With the Mongo db 3.2 release, you can use the new $filter aggregation operator to filter an array during projection, which includes all the matches in the array
db.test.aggregate([
{$match: {'features': {$elemMatch : {"properties.TYPE": '8003' }}},
{$project: {
features: {$filter: {
input: '$features',
as: 'feature',
cond: {$eq: ['$$feature.properties.TYPE', '8003']}
}}
}}
]);
If you just want the first element of the results, you can use the positional $ operator like below :
db.geo.find( { "features.properties.TYPE":"8003"}, { "features.$": 1 } )
$elemMatch operator returns only first element matching the $elemMatch condition in query result.
Please try executing following query
db.geo.find({
features: {
$elemMatch: {
"properties.TYPE": "8003"
}
}
}, {
features: {
$elemMatch: {
"properties.TYPE": "8003"
}
}
})
Please refer the documentation of $elemMatch operator as described in below mentioned URL
https://docs.mongodb.com/manual/reference/operator/projection/elemMatch/