I'm trying to execute a query like:
{array.0.property: {$ne: null}}.
It return nothing even if all documents have this property different from null.
After some tests i noticed that it work using $elemMatch, but i need to query only for the first element of the array.
The first element is to be considered as "Master" where all query should search.
I can't change document "schema".
Anyone know ho to solve this problem?
I'm using Mongodb 3.6.8.
Thanks in advice.
Example query:
db.getCollection('tasks').find({'details.0.code': {$ne: null}});
Example documents:
{
"name": "test",
"date": 2018-07-17 06:30:00.000Z,
.....,
"details": [
{
"code": '123',
"description": 'something',
"resolutionYear": 2018
},
{
"code": null,
"description": 'secondary',
"resolutionYear": 2019
}
]
},
{
"name": "exam",
"date": 2018-09-20 09:00:00.000Z,
.....,
"details": [
{
"code": null,
"description": 'exam',
"resolutionYear": null
}
]
}
Related
let's say I have a collection like so:
{
"id": "2902-48239-42389-83294",
"data": {
"location": [
{
"country": "Italy",
"city": "Rome"
}
],
"time": [
{
"timestamp": "1626298659",
"data":"2020-12-24 09:42:30"
}
],
"details": [
{
"timestamp": "1626298659",
"data": {
"url": "https://example.com",
"name": "John Doe",
"email": "john#doe.com"
}
},
{
"timestamp": "1626298652",
"data": {
"url": "https://www.myexample.com",
"name": "John Doe",
"email": "doe#john.com"
}
},
{
"timestamp": "1626298652",
"data": {
"url": "http://example.com/sub/directory",
"name": "John Doe",
"email": "doe#johnson.com"
}
}
]
}
}
Now the main focus is on the array of subdocument("data.details"): I want to get output only of relevant matches e.g:
db.info.find({"data.details.data.url": "example.com"})
How can I get a match for all "data.details.data.url" contains "example.com" but won't match with "myexample.com". When I do it with $regex I get too many results, so if I query for "example.com" it also return "myexample.com"
Even when I do get partial results (with $match), It's very slow. I tried this aggregation stages:
{ $unwind: "$data.details" },
{
$match: {
"data.details.data.url": /.*example.com.*/,
},
},
{
$project: {
id: 1,
"data.details.data.url": 1,
"data.details.data.email": 1,
},
},
I really don't understand the pattern, with $match, sometimes Mongo do recognize prefixes like "https://" or "https://www." and sometime it does not.
More info:
My collection has dozens of GB, I created two indexes:
Compound like so:
"data.details.data.url": 1,
"data.details.data.email": 1
Text Index:
"data.details.data.url": "text",
"data.details.data.email": "text"
It did improve the query performance but not enough and I still have this issue with the $match vs $regex. Thanks for helpers!
Your mistake is in the regex. It matches all URLs because the substring example.com is in all URLs. For example: https://www.myexample.com matches the bolded part.
To avoid this you have to use another regex, for example that just start with that domain.
For example:
(http[s]?:\/\/|www\.)YOUR_SEARCH
will check that what you are searching for is behind an http:// or www. marks.
https://regex101.com/r/M4OLw1/1
I leave you the full query.
[
{
'$unwind': {
'path': '$data.details'
}
}, {
'$match': {
'data.details.data.url': /(http[s]?:\/\/|www\.)example\.com/)
}
}
]
Note: you must scape special characters from the regex. A dot matches any character and the slash will close your regex causing an error.
I got a big array with data in the following format:
{
"application": "myapp",
"buildSystem": {
"counter": 2361.1,
"hostname": "host.com",
"jobName": "job_name",
"label": "2361",
"systemType": "sys"
},
"creationTime": 1517420374748,
"id": "123",
"stack": "OTHER",
"testStatus": "PASSED",
"testSuites": [
{
"errors": 0,
"failures": 0,
"hostname": "some_host",
"properties": [
{
"name": "some_name",
"value": "UnicodeLittle"
},
<MANY MORE PROPERTIES>,
{
"name": "sun",
"value": ""
}
],
"skipped": 0,
"systemError": "",
"systemOut": "",
"testCases": [
{
"classname": "IdTest",
"name": "has correct representation",
"status": "PASSED",
"time": "0.001"
},
<MANY MORE TEST CASES>,
{
"classname": "IdTest",
"name": "normalized values",
"status": "PASSED",
"time": "0.001"
}
],
"tests": 8,
"time": 0.005,
"timestamp": "2018-01-31T17:35:15",
"title": "IdTest"
}
<MANY MORE TEST SUITES >,
]}
Where I can distinct three main structures with big data: TestSuites, Properties, and TestCases. My task is to sum all times from each TestSuite so that I can get the total duration of the test. Since the properties and TestCases are huge, the query cannot complete. I would like to select only the "time" value from TestSuites, but it kind of conflicts with the "time" of TestCases in my query:
db.my_tests.find(
{
application: application,
creationTime:{
$gte: start_date.valueOf(),
$lte: end_date.valueOf()
}
},
{
application: 1,
creationTime: 1,
buildSystem: 1,
"testSuites.time": 1,
_id:1
}
)
Is it possible to project only the "time" properties from TestSuites without loading the whole schema? I already tried testSuites: 1, testSuites.$.time: 1 without success. Please notice that TestSuites is an array of one element with a dictionary.
I already checked this similar post without success:
Mongodb update the specific element from subarray
Following code prints duration of each TestSuite:
query = db.my_collection.aggregate(
[
{$match: {
application: application,
creationTime:{
$gte: start_date.valueOf(),
$lte: end_date.valueOf()
}
}
},
{ $project :
{ duration: { $sum: "$testSuites.time"}}
}
]
).forEach(function(doc)
{
print(doc._id)
print(doc.duration)
}
)
Is it possible to project only the "time" properties from TestSuites
without loading the whole schema? I already tried testSuites: 1,
testSuites.$.time
Answering to your problem of prejecting only the time property of the testSuites document you can simply try projecting it with "testSuites.time" : 1 (you need to add the quotes for the dot notation property references).
My task is to sum all times from each TestSuite so that I can get the
total duration of the test. Since the properties and TestCases are
huge, the query cannot complete
As for your task, i suggest you try out the mongodb's aggregation framework for your calculations documents tranformations. The aggregations framework option {allowDiskUse : true} will also help you if you are proccessing "large" documents.
I am working on mongodb Aggregation query but i don't know how to get the array value from the JSON by joining two collection, please go through my below sample JSON.
COKE Collection
[{
"name": "Mirinda",
"_id": "894567894769476948"
}, {
"name": "COKE",
"_id": "857856856879694769"
}, {
"name": "PEPSI",
"_id": "785485686846684684"
}]
COKE Order Collection
{
"_id": "0908080808031338013101",
"drink": [{
"name": "Mirinda",
"_id": "894567894769476948"
}, {
"name": "COKE",
"_id": "857856856879694769"
}, {
"name": "PEPSI",
"_id": "785485686846684684"
}]
}
Expected OutPut:
Miranda name and _id should come of Orders collection by passing _id.
Above sample son i want to get the name value by joining the collections _id, please kindly go through my post and let me know if you have any suggestion.
I have the following structure in MongoDB and I try to remove the documents that contains specific tags. I can't seem to be able to get the $pull work.
In this example, I would like to pull the nested doc that has has tags :["BB"]
Any help will be appreciated !
{
"_id": 123,
"socialItems": {
"facebook": [{
"name": "firstFacebook",
"id": 2
}, {
"name": "secondFB",
"id": 43
}],
"instagram": [{
"name": "firstNstagram",
"id": 4
}],
"pc": [{
"name": "firstPC",
"id": 55,
"tags": [
"ab"
]
}, {
"name": "secondPC",
"id": 66,
"tags": [
"BB"
]
}]
}
}
I assume you are trying to drop the nested 'pc' doc, from the array? You also don't mention if you're using a specific driver for this, so I've assumed you're running this in the Mongo shell.
The following will remove documents from the 'pc' property, when containing the 'BB' tag.
db.collectionName.update({'socialItems.pc.tags': 'BB'}, {$pull: {'socialItems.pc': {tags: 'BB'}}})
I have a mongo db with this model:
_id: ObjectId("5705005b240166e927f841cb")
chapters: {
type: Array,
default: [
{
"id":"capitulo_0",
"active": true,
"title": "CAPÍTULO 0 - INTRODUCCIÓN",
"sections": [
{
"title": "Institucional",
"type": "Video",
"id": "d74fb24654a2",
"url": "jPTG5P0528k",
"active": true
}
]
},
{
"id":"capitulo_1",
"active": false,
"title": "CAPÍTULO 1 - BIENVENIDA",
"sections": [
{
"title": "Introducción",
"type": "Video",
"url": "j2TG1P05k8k",
"id": "b2454d7f66de",
"active": false
}
]
},
...
]
}
For the query i have the user_id and the id of the sections and i need update the active field of the sections array.
I'm doing this:
User.findOneAndUpdate({_id: userId, 'chapters.sections':{$elemMatch: {id:sectionId}}}, {$set: {'sections.$.active': false}}).exec(function (err, doc) {console.log(doc)});
The active field not change.
How can I do it this query?
Thank's
I dont have your data so run this:
User.findOne({_id: userId, 'chapters.sections':{$elemMatch: {id:sectionId}}})
and see if you get response and record will be found, because your update looks fine.
UPDATE:
After seeing your data I think you are missing chapters in your query
User.findOneAndUpdate({_id: userId, 'chapters.sections':{$elemMatch: {id:sectionId}}}, {$set: {'chapters.sections.$.active': false}}).exec(function (err, doc) {console.log(doc)});
I hope this helps