MongoDB - Query within an in-memory BsonDocument - mongodb

I am reading a single document into a BsonDocument object. Having read the document from MongoDB I'd like to query the document in-memory.
My doc looks like this:
{
"_id": {
"$binary": "DYibd4bSz0SFXTTmY46gOQ==",
"$type": "03"
},
"title": "XYZ 2011",
"pages": [
{
"pagetype": "contactcapture",
"pagetitle": "Contact",
"questions": [
{
"qtype": "text",
"text": "Firstname",
"name": "firstname"
},
{
"qtype": "text",
"text": "Surname",
"name": "surname"
},
{
"qtype": "text",
"text": "Company",
"name": "companyname"
}
]
},
{
"pagetype": "question",
"pagetitle": "Question 1",
"questions": [
{
"qtype": "radio",
"text": "What drink?",
"name": "drink",
"answers": [
{
"text": "Tea"
},
{
"text": "Coffee"
},
{
"text": "Hot chocolate"
},
{
"text": "Water"
}
]
}
]
},
{
"pagetype": "question",
"pagetitle": "Question 2",
"questions": [
{
"qtype": "check",
"text": "Accompaniments?",
"name": "accompaniments",
"answers": [
{
"text": "Nuts"
},
{
"text": "Crisps"
},
{
"text": "Biscuits"
}
]
}
]
},
{
"pagetype": "question",
"pagetitle": "Question 3",
"questions": [
{
"qtype": "radio",
"text": "When would you like that?",
"name": "when",
"answers": [
{
"text": "Immediately"
},
{
"text": "10 minutes"
},
{
"text": "Half-an-hour"
}
]
},
{
"qtype": "text",
"text": "Anything else with that?",
"name": "anythingelse"
}
]
}
]
}
I want to get all pages that have a pagetype="question". I'm currently doing it as follows:
BsonDocument profileDocument= profilesCollection.FindOneByIdAs<MongoDB.Bson.BsonDocument>(binaryId);
BsonElement pagesElement = profileDocument.GetElement("pages");
BsonArray pages=profileDocument.GetElement("pages").Value.AsBsonArray;
foreach (BsonValue pageV in pages.Values)
{
BsonDocument page = pageV.AsBsonDocument;
if (page["pagetype"].AsString == "question")
{
sb.Append("<br />Question Page:" + page.ToJson());
}
}
The code seems a little verbose and complex - I just wondered if there is a better way of doing this? Thanks

Assuming that the data type of profilesCollection is MongoCollection<BsonDocument>, you could shorten the code so something like this:
var profileDocument = profilesCollection.FindOneById(binaryId);
foreach (BsonDocument page in profileDocument["pages"].AsBsonArray) {
if (page["pagetype"].AsString == "question") {
sb.Append("<br />Question Page:" + page.ToJson());
}
}

Related

Updating array list in Mongo DB

I want to update the Status field inside array list of Slots where id = "".
Sample data
{
"_id": ObjectId("621e816e7a938400016c5c64"),
"Resource": "abc#gmail.com",
"School": {
"Class": [
{
"Type": "ABC",
"Slots": [
{
"id": "",
"Duration": "1 week",
"Status": "Released",
"Selected": true
},
{
"id": "123",
"Duration": "1 week",
"Status": "Released",
"Selected": true
}
]
}
]
}
}
This is how I am approaching:
db.getCollection("XYZ").update({
"Resource": "abc#gmail.com",
"School.Class": {
"$elemMatch": {
"Type": "ABC",
"Slots.Status": "Released",
"Slots.id": "",
"Slots.Duration": "1 week"
}
}
},
{
$set: {
"School.Class.$[outer].Slots.$[inner].Status": "Confirmed"
}
},
{
"arrayFilters": [
{
"outer.Type": "ABC"
},
{
"inner.Duration": "1 week"
}
]
})
But it is updating the status as confirmed for the both the array list.How can I update the particular field where "Slots.id" : "" . Please forgive me in case of any misalignment or brackets missing in data
If I've understood correctly you are almost there, since you want to update only values where id is "" you have to add that condition into arrayFilters: "inner.id": "".
db.collection.update({
"Resource": "abc#gmail.com",
"School.Class": {
"$elemMatch": {
"Type": "ABC",
"Slots.Status": "Released",
"Slots.id": "",
"Slots.Duration": "1 week"
}
}
},
{
$set: {
"School.Class.$[outer].Slots.$[inner].Status": "Confirmed"
}
},
{
"arrayFilters": [
{
"outer.Type": "ABC"
},
{
"inner.Duration": "1 week",
"inner.id": "" // <--- This line
}
]
})
Example here

MongoDB lookup with multiple nested levels

In my application, I have a section of comments and replies under some documents.
Here's how my database schema looks like
db.updates.insertOne({
"_id": "62347813d28412ffd82b551d",
"documentID": "17987e64-f848-40f3-817e-98adfd9f4ecd",
"stream": [
{
"id": "623478134c449b218b68f636",
"type": "comment",
"text": "Hey #john, we got a problem",
"authorID": "843df3dbbdfc62ba2d902326",
"taggedUsers": [
"623209d2ab26cfdbbd3fd348"
],
"replies": [
{
"id": "623478284c449b218b68f637",
"type": "reply",
"text": "Not sure, let's involve #jim here",
"authorID": "623209d2ab26cfdbbd3fd348",
"taggedUsers": [
"26cfdbbd3fd349623209d2ab"
]
}
]
}
]
})
db.users.insertMany([
{
"_id": "843df3dbbdfc62ba2d902326",
"name": "Manager"
},
{
"_id": "623209d2ab26cfdbbd3fd348",
"name": "John"
},
{
"_id": "26cfdbbd3fd349623209d2ab",
"name": "Jim"
},
])
I want to join those two collections, and replace user ids with complete user information on all levels. So the final JSON should look like this
{
"_id": "62347813d28412ffd82b551d",
"documentID": "17987e64-f848-40f3-817e-98adfd9f4ecd",
"stream": [
{
"id": "623478134c449b218b68f636",
"type": "comment",
"text": "Hey #john, we got a problem",
"author": {
"_id": "843df3dbbdfc62ba2d902326",
"name": "Manager"
},
"taggedUsers": [
{
"_id": "623209d2ab26cfdbbd3fd348",
"name": "John"
}
],
"replies": [
{
"id": "623478284c449b218b68f637",
"type": "reply",
"text": "Not sure, let's involve #jim here",
"author": {
"_id": "623209d2ab26cfdbbd3fd348",
"name": "John"
},
"taggedUsers": [
{
"_id": "26cfdbbd3fd349623209d2ab",
"name": "Jim"
}
]
}
]
}
]
}
I know how to do the $lookup on the top-level fields, including pipelines, but how can I do with the nested ones?

check if a field of type array contains an array

Im using mongoose, I have the following data of user collection:
[{
"_id": "1",
"notes": [
{
"value": "A90",
"text": "math"
},
{
"value": "A80",
"text": "english"
},
{
"value": "A70",
"text": "art"
}
]
},
{
"_id": "2",
"notes": [
{
"value": "A90",
"text": "math"
},
{
"value": "A80",
"text": "english"
}
]
},
{
"_id": "3",
"notes": [
{
"value": "A80",
"text": "art"
}
]
}]
and I have as a parameters the following array: [ "A90", "A80" ]
so I want to make a query to use this array to return only the records that have all the array items in the notes (value) table.
So for the example above it will return:
[{
"_id": "1",
"notes": [
{
"value": "A90",
"text": "math"
},
{
"value": "A80",
"text": "english"
},
{
"value": "A70",
"text": "art"
}
]
},
{
"_id": "2",
"notes": [
{
"value": "A90",
"text": "math"
},
{
"value": "A80",
"text": "english"
}
]
}]
I tried the following find query:
{ "notes": { $elemMatch: { value: { $in: valuesArray } } }}
but it returns a record even if just one element in valuesArray exist.
it turned out to be quite easy:
find({ "notes.value": { $all: arrayValues } })

REST API 'Create Passenger Name Record' Warning and errors

The below attached warnings and error occurred while testing Booking seat.
There is no any proper documentation of Create Passenger Name Record REST API Call, the description and schema are meaning less. In description there are 266 parameters are required true to send a request.
Do you have any proper documentation where i can get all the required parameters detailed information? Like What is SegmentNumber how can i get?
Working flow( For Single trip) :
Get the origin, destination, date, number of seats required.
Send all required parms to Bargain Finder Max, get the response
Send Require params to book a seat. Create Passenger Name Record
Request
{
"CreatePassengerNameRecordRQ": {
"targetCity": "3QND",
"Profile": {
"UniqueID": {
"ID": "ABCD1EF"
}
},
"AirBook": {
"OriginDestinationInformation": {
"FlightSegment": [{
"ArrivalDateTime": "2017-04-30",
"DepartureDateTime": "2017-04-30T13:55",
"FlightNumber": "309",
"NumberInParty": "1",
"ResBookDesigCode": "V",
"Status": "NN",
"DestinationLocation": {
"LocationCode": "KHI"
},
"MarketingAirline": {
"Code": "PK",
"FlightNumber": "309"
},
"MarriageGrp": "O",
"OriginLocation": {
"LocationCode": "ISB"
}
}]
}
},
"AirPrice": {
"PriceRequestInformation": {
"OptionalQualifiers": {
"MiscQualifiers": {
"TourCode": {
"Text": "TEST1212"
}
},
"PricingQualifiers": {
"PassengerType": [{
"Code": "CNN",
"Quantity": "1"
}]
}
}
}
},
"MiscSegment": {
"DepartureDateTime": "2017-04-30",
"NumberInParty": 1,
"Status": "NN",
"Type": "OTH",
"OriginLocation": {
"LocationCode": "ISB"
},
"Text": "TEST",
"VendorPrefs": {
"Airline": {
"Code": "PK"
}
}
},
"SpecialReqDetails": {
"AddRemark": {
"RemarkInfo": {
"FOP_Remark": {
"Type": "CHECK",
"CC_Info": {
"Suppress": true,
"PaymentCard": {
"AirlineCode": "PK",
"CardSecurityCode": "1234",
"Code": "VI",
"ExpireDate": "2012-12",
"ExtendedPayment": "12",
"ManualApprovalCode": "123456",
"Number": "4123412341234123",
"SuppressApprovalCode": true
}
}
},
"FutureQueuePlaceRemark": {
"Date": "12-21",
"PrefatoryInstructionCode": "11",
"PseudoCityCode": "IPCC1",
"QueueIdentifier": "499",
"Time": "06:00"
},
"Remark": [{
"Type": "Historical",
"Text": "TEST HISTORICAL REMARK"
},
{
"Type": "Invoice",
"Text": "TEST INVOICE REMARK"
},
{
"Type": "Itinerary",
"Text": "TEST ITINERARY REMARK"
},
{
"Type": "Hidden",
"Text": "TEST HIDDEN REMARK"
}]
}
},
"AirSeat": {
"Seats": {
"Seat": [{
"NameNumber": "1.1",
"Preference": "AN",
"SegmentNumber": "0"
},
{
"NameNumber": "2.1",
"Preference": "AN",
"SegmentNumber": "1"
},
{
"NameNumber": "3.1",
"Preference": "AN",
"SegmentNumber": "1"
}]
}
},
"SpecialService": {
"SpecialServiceInfo": {
"Service": [{
"SSR_Code": "OSI",
"PersonName": {
"NameNumber": "testing"
#},
"Text": "TEST1",
"VendorPrefs": {
"Airline": {
"Code": "PK"
}
}
}]
}
}
},
"PostProcessing": {
"RedisplayReservation": true,
"ARUNK": "",
"QueuePlace": {
"QueueInfo": {
"QueueIdentifier": [{
"Number": "100",
"PrefatoryInstructionCode": "11"
}]
}
},
"EndTransaction": {
"Source": {
"ReceivedFrom": "SWS TEST"
}
}
}
}
}
Response:
{
"CreatePassengerNameRecordRS": {
"ApplicationResults": {
"status": "NotProcessed",
"Error": [
{
"type": "Application",
"timeStamp": "2017-03-08T04:10:41.317-06:00",
"SystemSpecificResults": [
{
"Message": [
{
"code": "ERR.SP.BUSINESS_ERROR",
"content": "PNR has not been created successfully, see remaining messages for details"
}
]
}
]
}
],
"Warning": [
{
"type": "BusinessLogic",
"timeStamp": "2017-03-08T04:10:40.628-06:00",
"SystemSpecificResults": [
{
"Message": [
{
"code": "WARN.SP.PROVIDER_ERROR",
"content": "NO PROFILE FOUND FOR NAME"
}
]
}
]
},
{
"type": "Validation",
"timeStamp": "2017-03-08T04:10:40.655-06:00",
"SystemSpecificResults": [
{
"Message": [
{
"code": "WARN.SWS.CLIENT.VALIDATION_FAILED",
"content": "Request contains incorrect values: Wrong dateTime format"
}
]
}
]
},
{
"type": "BusinessLogic",
"timeStamp": "2017-03-08T04:10:40.919-06:00",
"SystemSpecificResults": [
{
"Message": [
{
"code": "WARN.SWS.HOST.ERROR_IN_RESPONSE",
"content": "FORMAT, CHECK SEGMENT NUMBER-0003"
}
]
}
]
},
{
"type": "BusinessLogic",
"timeStamp": "2017-03-08T04:10:41.024-06:00",
"SystemSpecificResults": [
{
"Message": [
{
"code": "WARN.SWS.HOST.ERROR_IN_RESPONSE",
"content": ".DTE.NOT ENT BGNG WITH"
}
]
}
]
},
{
"type": "BusinessLogic",
"timeStamp": "2017-03-08T04:10:41.062-06:00",
"SystemSpecificResults": [
{
"Message": [
{
"code": "WARN.SWS.HOST.ERROR_IN_RESPONSE",
"content": "\u0087ND NAMES\u0087"
}
]
}
]
},
{
"type": "BusinessLogic",
"timeStamp": "2017-03-08T04:10:41.096-06:00",
"SystemSpecificResults": [
{
"Message": [
{
"code": "WARN.SWS.HOST.ERROR_IN_RESPONSE",
"content": "\u0087ND NAMES\u0087"
}
]
}
]
},
{
"type": "BusinessLogic",
"timeStamp": "2017-03-08T04:10:41.129-06:00",
"SystemSpecificResults": [
{
"Message": [
{
"code": "WARN.SWS.HOST.ERROR_IN_RESPONSE",
"content": "\u0087ND NAMES\u0087"
}
]
}
]
},
{
"type": "BusinessLogic",
"timeStamp": "2017-03-08T04:10:41.166-06:00",
"SystemSpecificResults": [
{
"Message": [
{
"code": "WARN.SWS.HOST.ERROR_IN_RESPONSE",
"content": "NO ARNK INSERTED"
}
]
}
]
},
{
"type": "BusinessLogic",
"timeStamp": "2017-03-08T04:10:41.229-06:00",
"SystemSpecificResults": [
{
"Message": [
{
"code": "WARN.SWS.HOST.ERROR_IN_RESPONSE",
"content": "NEED PHONE FIELD - USE 9"
}
]
}
]
}
]
},
"TravelItineraryRead": {
"TravelItinerary": {
"CustomerInfo": {
},
"ItineraryInfo": {
"ReservationItems": {
"Item": [
{
"RPH": "1",
"MiscSegment": {
"DayOfWeekInd": "7",
"DepartureDateTime": "04-30",
"NumberInParty": "01",
"SegmentNumber": "0001",
"Status": "NN",
"Type": "OTH",
"IsPast": false,
"OriginLocation": {
"LocationCode": "ISB"
},
"Text": [
"TEST"
],
"Vendor": {
"Code": "PK"
}
}
}
]
}
},
"ItineraryRef": {
"AirExtras": false,
"InhibitCode": "U",
"PartitionID": "AA",
"PrimeHostID": "1B",
"Header": [
"CURRENTLY DISPLAYING A PNR OWNED BY THE SABRE PRIME HOST",
"RULES AND FUNCTIONALITY FOR THAT PRIME HOST WILL APPLY"
],
"Source": {
"PseudoCityCode": "3QND",
"ReceivedFrom": "SWS TEST"
}
},
"SpecialServiceInfo": [
{
"RPH": "001",
"Type": "GFX",
"Service": {
"SSR_Code": "OSI",
"Airline": {
"Code": "PK"
},
"Text": [
"TEST1-TESTING"
]
}
}
]
}
}
},
"Links": [
{
"rel": "self",
"href": "https:\/\/api.sabre.com\/v1.0.0\/passenger\/records?mode=create"
},
{
"rel": "linkTemplate",
"href": "https:\/\/api.sabre.com\/\/passenger\/records?mode="
}
]
}
Please avoid posting the same questions. Here's an answer I just posted regarding the required elements: https://stackoverflow.com/a/42671412/3701641
About the segment number, they represent the itinerary segments, you are adding one flight segment, so the segment number associated with that would be 1.

MongoDB query, project nested docs?

I was wondering if this is possible, or do I need to use the aggregation pipeline instead?
I have read posts such as this, and intuitively feel like it's possible.
Example of docs:
{
"_id": ObjectID("5143ddf3bcf1bfab37d9c6f"),
"permalink": "btxcacmbqkxbpgtpeero",
"author": "machine",
"title": "Declaration of Independence",
"tags": [
"study",
"law"
],
"comments": [
{
"body": "comment 1",
"email": "email_1#test.com",
"author": "machine_1"
},
{
"body": "comment 2",
"email": "email_2#test.com",
"author": "machine_2"
},
{
"body": "comment 3",
"email": "email_3#test.com",
"author": "machine_3"
},
]
"date": ISODate("2013-03-16T02:50:27.878Z")
}
I am trying to access a particular comment in "comments" by it's index position using dot notation in the projection field, with the following:
db.collection.find({permalink: "btxcacmbqkxbpgtpeero"}, {'comments.0.1.': 1})
Where comments.0 is the first item in the field: the array, and .1 is the second comment in the array.
The result I am getting:
{ "_id" : ObjectID("5143ddf3bcf1bfab37d9c6f"), "comments" : [ { }, { }, { } ] }
If I take away the .1, leaving just comments.0, I get the same result:
{ "_id" : ObjectID("5143ddf3bcf1bfab37d9c6f"), "comments" : [ { }, { }, { } ] }
If I take away the .0, leaving just comments, I get the comments still inside their array:
[
{
"body": "comment 1",
"email": "email_1#test.com",
"author": "machine_1"
},
{
"body": "comment 2",
"email": "email_2#test.com",
"author": "machine_2"
},
{
"body": "comment 3",
"email": "email_3#test.com",
"author": "machine_3"
}
]
Can this be done? If so, how?
without aggregation:
db.collection.find({
permalink:"btxcacmbqkxbpgtpeero"
},
{
comments:{
$slice:[
0,
1
]
}
})
returns
{
"_id":ObjectId("583af24824168f5cc566e1e9"),
"permalink":"btxcacmbqkxbpgtpeero",
"author":"machine",
"title":"Declaration of Independence",
"tags":[
"study",
"law"
],
"comments":[
{
"body":"comment 1",
"email":"email_1#test.com",
"author":"machine_1"
}
]
}
try it online: mongoplayground.net/p/LGbVWPyVkFk
with aggregation:
db.collection.aggregate([
{
$match:{
permalink:"btxcacmbqkxbpgtpeero"
}
},
{
$project:{
comment:{
$arrayElemAt:[
"$comments",
0
]
}
}
}
])
returns
{
"_id":ObjectId("583af24824168f5cc566e1e9"),
"comment":{
"body":"comment 1",
"email":"email_1#test.com",
"author":"machine_1"
}
}