MongoDB query double nested array - mongodb

Below is my mongo db document named business
{
"_id": ObjectId("5be8e24a6600321ead321466"),
"business_id": "r89Re4FNgVWHgBfjCVZyVw",
"name": "Harlow",
"neighborhood": "Ville-Marie",
"address": "438 Place Jacques Cartier",
"city": "Montréal",
"state": "QC",
"postal_code": "H2Y 3B3",
"stars": 3.5,
"attributes": {
"Alcohol": "full_bar",
"BikeParking": "True",
"BusinessAcceptsCreditCards": "True",
"BusinessParking": "{'garage': False, 'street': False, 'validated': False, 'lot': False, 'valet': False}",
"Caters": "False",
"GoodForMeal": "{'dessert': False, 'latenight': False, 'lunch': False, 'dinner': False, 'breakfast': False, 'brunch': False}",
"RestaurantsDelivery": "False",
"RestaurantsGoodForGroups": "True",
},
"categories": "Nightlife, Bars, American (Traditional), Tapas/Small Plates, Poutineries, Supper Clubs, Restaurants, Tapas Bars",
}
Question:In the above collection named business i need to Find all restaurants which provides meal for lunch. (need to Check attributes-GoodForMeal-lunch)
it is nested array. please suggest me how can this be done with mongo db

Related

Fast Searching Based on "custom fields" along with other fields

We have a legacy implementation of User Groups, which is way more than it implies. Users can be assigned to a group and you can create a hierarchy of groups. Groups can also have system wide permissions assigned to them, or a group can be used on some other module for permissions. You can even do a permission where it's something complicated like
((In Group1 or Group2) and (In Group3 and Group4)) or (In Group5 and (not IN Group1 or Group2))
When a permission like this is created, it will actually select all the users that match this, create a "derived group" and then assign those users to the new group.
In our new application, we have a completely different permissions system that handles these sorts of use cases pretty well, with it also being attribute based, rather than group/role based.
That being said, groups are still used for other things, other than permissions. We might build a report based upon a group, or send out emails to a group, etc. We still need this functionality.
It also looks like we're moving our current user information, into Mongo DB due to the fact that each client can customize the fields that are available for a user to populate, so a user might have a "job title" for one client, but another they would have a "designation", or "position". We call these "custom fields". The client can create as many of these fields as they want.
So that's the back story. My issue is that I don't really want to create a new "groups" implementation, since all we really need is a way to create and save filters for users, so when we need to send out an email to a specific subset of users, it will either use a filter that has already been saved, or create a new one.
So this is the original format for the user document in MongoDB:
{
"id": 123456,
"username": "john.smith#domain.com",
"first_name": "John",
"last_name": "Smith",
"email": "john.smith#domain.com",
"employee_type": "permanent",
"account": {
"enabled": true,
"locked": false,
"redeem_only": false
},
"custom_fields": {
"job_title": "Cashier",
"branch_code": "000123",
"social_team_name": "The Terrible Trolls"
}
},
{
"id": 123457,
"username": "jane.smith#domain.com",
"first_name": "Jane",
"last_name": "Smith",
"email": "john.smith#domain.com",
"employee_type": "permanent",
"account": {
"enabled": true,
"locked": false,
"redeem_only": false
},
"custom_fields": {
"job_title": "Mortgage Consultant",
"branch_code": "000123",
"social_team_name": "Team Savage"
}
},
{
"id": 123458,
"username": "morgan.jones#domain.com",
"first_name": "Morgan",
"last_name": "Jones",
"email": "morgan.jones#domain.com",
"employee_type": "permanent",
"account": {
"enabled": true,
"locked": false,
"redeem_only": false
},
"custom_fields": {
"job_title": "Regional Manager",
"branch_code": "000124",
"social_team_name": "The Terrible Trolls"
}
}
So we might want to create a filter where account.enabled = true AND employee_type='permanent' AND custom_fields.branch_code=000124. The filter could be any combination of fields in anyway.
Ultimately I'm wondering if this sort of structure is the best way to do this, I know I can use wildcard indexes to index the custom fields, but I'm still limited with regards to the amount of indexes I can create, so if a field is used in a query that isn't indexed, or we've hit our limit for creating indexes, then it's going to start slowing things down.
Another structure I saw is as follows:
{
"id": 123456,
"username": "john.smith#domain.com",
"first_name": "John",
"last_name": "Smith",
"email": "john.smith#domain.com",
"employee_type": "permanent",
"account": {
"enabled": true,
"locked": false,
"redeem_only": false
},
"custom_fields": [
{
"k": "Job Title",
"v": "Cashier"
},
{
"k": "Branch Code",
"v": "000123"
},
{
"k": "Social Team Name",
"v": "The Terrible Trolls"
}
]
},
{
"id": 123457,
"username": "jane.smith#domain.com",
"first_name": "Jane",
"last_name": "Smith",
"email": "john.smith#domain.com",
"employee_type": "permanent",
"account": {
"enabled": true,
"locked": false,
"redeem_only": false
},
"custom_fields": [
{
"k": "Job Title",
"v": "Mortgage Consultant"
},
{
"k": "Branch Code",
"v": "000123"
},
{
"k": "Social Team Name",
"v": "Team Savage"
}
]
},
{
"id": 123458,
"username": "morgan.jones#domain.com",
"first_name": "Morgan",
"last_name": "Jones",
"email": "morgan.jones#domain.com",
"employee_type": "permanent",
"account": {
"enabled": true,
"locked": false,
"redeem_only": false
},
"custom_fields": [
{
"k": "Job Title",
"v": "Regional Manager"
},
{
"k": "Branch Code",
"v": "000124"
},
{
"k": "Social Team Name",
"v": "The Terrible Trolls"
}
]
}
However, I'm not really sure if this would be better or not, as the problem still remains that we are limited by the amount of indexes we can create.
Is there a viable solution for this (links to articles/resources would be great), or am I going to end up saving a "filter", selecting all the users that apply to the filter and then assigning them to "filter" for easy lookup, but then have to rebuild every time a user updates their information, gets promoted, or anything else that changes the field values?

Updating Mongo DB collection field from object to array of objects

I had to change one of the fields of my collection in mongoDB from an object to array of objects containing a lot of data. New documents get inserted without any problem, but when attempted to get old data, it never maps to the original DTO correctly and runs into errors.
subject is the field that was changed in Students collection.
I was wondering is there any way to update all the records so they all have the same data type, without losing any data.
The old version of Student:
{
"_id": "5fb2ae251373a76ae58945df",
"isActive": true,
"details": {
"picture": "http://placehold.it/32x32",
"age": 17,
"eyeColor": "green",
"name": "Vasquez Sparks",
"gender": "male",
"email": "vasquezsparks#orbalix.com",
"phone": "+1 (962) 512-3196",
"address": "619 Emerald Street, Nutrioso, Georgia, 6576"
},
"subject":
{
"id": 0,
"name": "math",
"module": {
"name": "Advanced",
"semester": "second"
}
}
}
This needs to be updated to the new version like this:
{
"_id": "5fb2ae251373a76ae58945df",
"isActive": true,
"details": {
"picture": "http://placehold.it/32x32",
"age": 17,
"eyeColor": "green",
"name": "Vasquez Sparks",
"gender": "male",
"email": "vasquezsparks#orbalix.com",
"phone": "+1 (962) 512-3196",
"address": "619 Emerald Street, Nutrioso, Georgia, 6576"
},
"subject": [
{
"id": 0,
"name": "math",
"module": {
"name": "Advanced",
"semester": "second"
}
},
{
"id": 1,
"name": "history",
"module": {
"name": "Basic",
"semester": "first"
}
},
{
"id": 2,
"name": "English",
"module": {
"name": "Basic",
"semester": "second"
}
}
]
}
I understand there might be a way to rename old collection, create new and insert data based on old one in to new one. I was wondering for some direct way.
The goal is to turn subject into an array of 1 if it is not already an array, otherwise leave it alone. This will do the trick:
update args are (predicate, actions, options).
db.foo.update(
// Match only those docs where subject is an object (i.e. not turned into array):
{$expr: {$eq:[{$type:"$subject"},"object"]}},
// Actions: set subject to be an array containing $subject. You MUST use the pipeline version
// of the update actions to correctly substitute $subject in the expression!
[ {$set: {subject: ["$subject"] }} ],
// Do this for ALL matches, not just first:
{multi:true});
You can run this converter over and over because it will ignore converted docs.
If the goal is to convert and add some new subjects, preserving the first one, then we can set up the additional subjects and concatenate them into one array as follows:
var mmm = [ {id:8, name:"CORN"}, {id:9, name:"DOG"} ];
rc = db.foo.update({$expr: {$eq:[{$type:"$subject"},"object"]}},
[ {$set: {subject: {$concatArrays: [["$subject"], mmm]} }} ],
{multi:true});

Azure DevOps API - how to discover link between field and picklist

I'm trying to replicate an Azure DevOps process from one organization to another via the AZDO REST Api. I'm working on replicating the layout and am stuck because I can't discover the relationship between a custom field and a picklist when querying the source AZDO instance.
In my scenario I have a test work item type which I've called Issue. On the Issue interface I've created a custom field which is a picklist. While I can retrieve a list of lists via the Rest API and examine the field as well, I can't figure out how the two are related.
Here is a partial payload from the field:
{
"count": 39,
"value": [
...
{
"referenceName": "Custom.IssueSource",
"name": "Issue Source",
"type": "string",
"description": "Who is this attributed to",
"required": true,
"url": "https://dev.azure.com/MYORG/_apis/work/processes/f390103e-7097-4f19-b5b5-f9dbcf92bb6f/behaviors",
"customization": "custom"
},
... ]
}
and here is a partial payload from the lists get query which I used trial and error to determine was the picklist I've assigned:
{
"count": 10,
"value": [
...
{
"id": "2998d4e4-2bec-4935-98a1-b67a0b0b6d5d",
"name": "picklist_e854661e-8620-4ad9-be28-b974c5cb3a5d",
"type": "String",
"isSuggested": false,
"url": "https://dev.azure.com/MYORG/_apis/work/processes/lists/2998d4e4-2bec-4935-98a1-b67a0b0b6d5d"
},
...
]
}
Here is a partial layout response for the WIT:
{
"pages": [
{
"id": "d0171d51-ff84-4038-afc1-8800ab613160.System.WorkItemType.Details",
"inherited": true,
"label": "Details",
"pageType": "custom",
"visible": true,
"isContribution": false,
"sections": [
{
"id": "Section1",
"groups": [
...
{
"id": "bf03e049-5062-4d82-b91d-4396541fbed2",
"label": "Custom",
"isContribution": false,
"visible": true,
"controls": [
{
"id": "Custom.IssueSource",
"label": "Issue Source",
"controlType": "FieldControl",
"readOnly": false,
"visible": true,
"isContribution": false
}
]
}
]
},
... ]
}
Using fiddler against the AZDO web interface, the only time I see a reference to the picklist is from another non-AZDO API to https://dev.azure.com/MYORG/_apis/Contribution/dataProviders/query
Is there a way to discover the link via the AZDO Rest API? I saw this question which was similar but was about creating the link
Figured it out. Turns out you need to query from a different scope - work item tracking rather than work item tracking process:
https://dev.azure.com/MYORG/_apis/wit/fields/Custom.IssueSource?api-version=5.0-preview.2
returns
{
"name": "Issue Source",
"referenceName": "Custom.IssueSource",
"description": "Who is this attributed to",
"type": "string",
"usage": "workItem",
"readOnly": false,
"canSortBy": true,
"isQueryable": true,
...
"isIdentity": false,
--> "isPicklist": true,
"isPicklistSuggested": false,
--> "picklistId": "2998d4e4-2bec-4935-98a1-b67a0b0b6d5d",
"url": "https://dev.azure.com/MYORG/_apis/wit/fields/Custom.IssueSource"
}

How do I populate an embedded document attribute on mongoDB Atlas?

I've already successfully used an embedded document to create a nested amenities attribute, under a spot in my database, but now I'd like to populate it with true values. (by default they're false) The object that I created on mongoDB looks like this so far:
And on Postman, when I go to my spots index, this is what a spot looks like:
[
{
"amenities": {
"wifi": false,
"kitchen": false,
"breakfast": false,
"parking": false,
"pool": false,
"essentials": false
},
"_id": "5e4317871c9d440000b1613f",
"name": "Test home 1",
"latitude": 5.97,
"longitude": 62.54,
"city": "Los Angeles",
"state": "California",
"country": "United States",
"description": "This is a test description",
"occupancy": 4,
"bedrooms": 2,
"baths": 1,
"date": "2020-02-11T21:20:28.969Z"
}
]
How would I populate the amenities attribute on mongoDB? Do I need to add a line like this into the document on mongoDB?
amenities: { wifi: true, kitchen: true, breakfast: true, etc... }

Know Group name by Rest API

How do I know the exact name of the Groups in my VSTS workItems using Rest APIs.
I know the field names however As I do not know the group name or how to access the group. I am unable to add the field to the group
To get the group name(s), you can use the REST API to get process definition's Layout:
GET https://{accountName}.visualstudio.com/_apis/work/processdefinitions/{processId}/workItemTypes/{witRefName}/layout?api-version=4.1-preview
Such as
GET https://marinaliu.visualstudio.com/_apis/work/processdefinitions/c3c605d0-4ea8-492a-9d26-46612ccb51b1/workItemTypes/Microsoft.VSTS.WorkItemTypes.Bug/layout?api-version=4.1-preview
The response will look like:
{
"pages": [
{
"id": "Scrum.Bug.Bug",
"inherited": true,
"label": "Details",
"pageType": "custom",
"locked": false,
"visible": true,
"isContribution": false,
"sections": [
{
"id": "Section1",
"groups": [
...
{
"id": "2fe29062-685e-4e36-89ba-6415becaebd7",
"label": "Group1",
"isContribution": false,
"visible": true,
"controls": [
{
"id": "8c6bc312-cd08-44a7-a403-5bcbbe9baff1",
"label": "control",
"readOnly": false,
"visible": true,
"contribution": {
"contributionId": "ms-devlabs.vsts-extensions-multivalue-control.multivalue-form-control",
"inputs": {
"FieldName": "Microsoft.VSTS.Common.Activity",
"Values": "control value"
}
},
"isContribution": true
}
]
}
]
}
...
}
And you can get the group name from label parameter under sections and groups objects.