I have the following table structure for example - Users, Projects.
Users has_many Projects
Projects has_many Photos
But i want to embedded certain basic content of Projects and Photos into the Users Table so that i can reduce the number of database calls for certain pages.
Below is the structure i have come up with.
Users Table
[
{
"id": "LONG-MONGO-ID-HERE-USER-1",
"name": "Harsha MV",
"email": "harsha#mink7.com",
"gender": "male",
"telephone": "9986377561",
"is_pro": 1,
"projects": [
{
"id": "LONG-MONGO-ID-HERE-PROJECT-1",
"name": "Nike",
"url": "http://nike.com",
"logo": "logo_nike.jpg",
"photos": [
{
"title": "Some title for an Image",
"file": "project1_photo1.jpg"
},
{
"title": "another title for an Image",
"file": "project1_photo2.jpg"
}
]
},
{
"id": "LONG-MONGO-ID-HERE-PROJECT-2",
"name": "BMW",
"url": "http://bmw.com",
"logo": "logo_bmw.jpg",
"photos": [
{
"title": "Some title for an Image",
"file": "project2_photo1.jpg"
},
{
"title": "another title for an Image",
"file": "project2_photo2.jpg"
}
]
}
]
},
{
"id": "LONG-MONGO-ID-HERE-USER-2",
"name": "Pruthvi Gowda",
"email": "pruthvi#mink7.com",
"gender": "male",
"telephone": "9982318016",
"is_pro": 0,
"projects": [
{
"id": "LONG-MONGO-ID-HERE-PROJECT-3",
"name": "Adidas",
"url": "http://adidas.com",
"logo": "logo_adidas.jpg",
"photos": [
{
"title": "Some title for an Image",
"file": "project1_photo3.jpg"
},
{
"title": "another title for an Image",
"file": "project1_photo4.jpg"
}
]
},
{
"id": "LONG-MONGO-ID-HERE-PROJECT-2",
"name": "BMW",
"url": "http://bmw.com",
"logo": "logo_bmw.jpg",
"photos": [
{
"title": "Some title for an Image",
"file": "project2_photo1.jpg"
},
{
"title": "another title for an Image",
"file": "project2_photo2.jpg"
}
]
}
]
}
]
Projects Table
[
{
"id": "LONG-MONGO-ID-HERE-PROJECT-1",
"name": "Nike",
"url": "http://nike.com",
"logo": "logo_nike.jpg",
"about": "Lorem Ipsum is simply dummy text of the printing and typesetting industry.",
"testimonial": "e middle of text. All the Lorem Ipsum generators on the Internet tend",
"photos": [
{
"title": "Some title for an Image",
"description": "um is simply dummy text of the printing and t",
"file": "project1_photo1.jpg"
},
{
"title": "another title for an Image",
"description": "text of the printing and t um is simply dummy",
"file": "project1_photo2.jpg"
}
],
"user": {
"id": "LONG-MONGO-ID-HERE-USER-1",
"name": "Harsha MV",
"email": "harsha#mink7.com"
}
},
{
"id": "LONG-MONGO-ID-HERE-PROJECT-2",
"name": "BMW",
"url": "http://bmw.com",
"logo": "logo_bmw.jpg",
"about": "It is a long established fact that a reader will be distracted by the",
"testimonial": "from sections 1.10.32 and 1.10.33 of de Finibus Bonorum et Malorum",
"photos": [
{
"title": "Some title for an Image",
"description": "um is simply dummy text of the printing and t",
"file": "project2_photo1.jpg"
},
{
"title": "another title for an Image",
"description": "text of the printing and t um is simply dummy",
"file": "project2_photo2.jpg"
}
],
"user": {
"id": "LONG-MONGO-ID-HERE-USER-1",
"name": "Harsha MV",
"email": "harsha#mink7.com"
}
}
]
As I have understood MongoDb is all about replication of data. is this the right way of designing the database structure.
class User
include Mongoid::Document
field :first_name, type: String
field :last_name, type: String
field :company_name, type: String
embeds_many :projects, class_name: "Project"
has_many :projects, class_name: "Project"
end
Can i do something like the above so that i can save two instance of the same data.
But as you see in the embedded document i am not storing all the data from the projects - how can i strict it from adding all the data as embedded document but stored as a separate table?
It is not possible to add same model as both embedded and referenced collection. You can put the structure as same you have mentioned initially by referencing the project collection in user.
And create dummy model say ImportantProject which will be embedded in User and you can sync up the data project in this model while making changes in database.
Related
The default result of rendering FastJsonApi gem serialized_json like below:
render json: FlashcardSerializer.new(flashcards).serialized_json
would be something like this:
{
"data": [
{
"id": "1",
"type": "flashcard",
"attributes": {
"question": "why?",
"answer": "pretty good",
"slug": null
}
},
{
"id": "2",
"type": "flashcard",
"attributes": {
"question": "What is 0",
"answer": "it is 0",
"slug": null
}
}
]
}
I would rather add some extra information especially for pagination and I like the result to be something like this:
{
"data": [
{
"id": "1",
"type": "flashcard",
"attributes": {
"question": "why?",
"answer": "pretty good",
"slug": null
}
},
{
"id": "2",
"type": "flashcard",
"attributes": {
"question": "What is 0",
"answer": "it is 0",
"slug": null
}
},
"count":100,
"page":1,
]
}
I am aware of other available gems that manage pagination in API, and I know how to do it without Fastjson. The main issue here is that is there any way to get the aforementioned result from this gem without changing a lot in the code. Thanks
The desired document would be invalid according to the JSON API specification. You would need to include next and previous links in a link section. The current and total_count would belong in the meta section.
{
"data": [
{
"id": "1",
"type": "flashcard",
"attributes": {
"question": "why?",
"answer": "pretty good",
"slug": null
}
},
{
"id": "2",
"type": "flashcard",
"attributes": {
"question": "What is 0",
"answer": "it is 0",
"slug": null
}
},
]
"meta": {
"page": { "current": 1, "total": 100 }
},
"links": {
"prev": "/example-data?page[before]=yyy&page[size]=1",
"next": "/example-data?page[after]=yyy&page[size]=1"
},
}
Have a look at the JSON API specification before you continue designing the API.
You can pass these information into the serializer as an options argument
class FlashcardsController < ApplicationController
def index
render json: FlashcardSerializer.new(
flashcards, { links: {}, meta: { page: { current: 1 } }
).serialized_json
end
end
How you generate the data depends what you use to paginate.
If you design a new API, I would also recommend to use cursor based pagination rather than offset pagination because of it's limitations.
https://github.com/Netflix/fast_jsonapi#compound-document
https://github.com/Netflix/fast_jsonapi/blob/master/spec/lib/object_serializer_spec.rb#L8-L32
I have some code that was working just fine a few months ago, but something in the Graph API has changed and this no longer works. I am trying to create a message in an existing folder, by doing a POST to this url:
https://graph.microsoft.com/v1.0/users/jjones#transend.onmicrosoft.com/mailFolders/AAMkADNjAAA=/messages
(folder id shortened)
The call fails with http error 400, and the returned error is "UnableToDeserializePostBody". The input json is shown below. By experimentation I was able to trace the problem specifically to "singleValueExtendedProperties". I normally put several properties there, but for this test I removed all but the one you see. I have tried other properties as well, they all fail. This seems like some stupid formatting error but I can't see it. Any help appreciated.
{
"subject": "Test again",
"Sender": {
"emailAddress": {
"name": "John Doe",
"address": "missing#domain.com"
}
},
"body": {
"contentType": "TEXT",
"content": "This is a text message."
},
"toRecipients": [
{
"emailAddress": {
"name": "Jane Smith",
"address": "missing#domain.com"
}
}
],
"ccRecipients": [
{
"emailAddress": {
"name": "Bob Jones",
"address": "missing#domain.com"
}
}
],
"singleValueExtendedProperties": [
{
"propertyId": "SystemTime 0x0039",
"value": "1998-07-29T21:30:00.0000+00:00"
}
],
"importance": "normal"
}
The main problem here is you are specifying the property('propertyid') in singleValueExtendedProperties object is not valid. There are only 2 properties in singleValueExtendedProperties. One is id and the other is value.
Replace 'propertyId' with id.
I have tested it in POSTMAN with your payload changing the propertyId to id and it worked.
Request Body:-
{
"subject": "Test again",
"Sender": {
"emailAddress": {
"name": "John Doe",
"address": "missing#domain.com"
}
},
"body": {
"contentType": "TEXT",
"content": "This is a text message."
},
"toRecipients": [
{
"emailAddress": {
"name": "Jane Smith",
"address": "missing#domain.com"
}
}
],
"ccRecipients": [
{
"emailAddress": {
"name": "Bob Jones",
"address": "missing#domain.com"
}
}
],
"singleValueExtendedProperties": [
{
"id": "SystemTime 0x0039",
"value": "1998-07-29T21:30:00.0000+00:00"
}
],
"importance": "normal"
}
I am creating a travel app which uses a backend Rails API. I've decided to use the Fast JSON API to serialize my data. I have a list of countries; each country has many cities, and each city has many attractions.
These are a list of my associations between my models.
Country.rb
has_many :cities
has_many :attractions, through: :locality
Localities.rb
has_many :attractions
belongs_to :country
Attraction.rb
belongs_to :locality
When I serialize my data for an individual attraction, I would like to include only the name attribute of the city and the name attribute of the country it belongs to. I am currently doing this by adding the optional parameter to include the locality and country name.
def show
attraction = Attraction.find_by(slug: params[:slug])
options = {}
options[:include] = [:locality, :'locality.country.name']
render json: AttractionSerializer.new(attraction, options).serialized_json
end
However, this gives all the attributes and relationships of the country, including a list of all unrelated localities nested within the country, which will become really inefficient when my dataset becomes larger. See below:
{
"data": {
"id": "1",
"type": "attraction",
"attributes": {
"name": "Plaza de EspaƱa",
"description": "Site of the World Exposition in 1929",
"types": null,
"latitude": 40.4232824,
"longitude": -3.7107257,
"slug": "plaza-de-espana",
"locality": {
"id": 1,
"name": "Seville",
"country_id": 168,
"created_at": "2020-06-10T05:43:47.474Z",
"updated_at": "2020-06-10T05:43:47.474Z",
"slug": "seville",
"latitude": 37.3886303,
"longitude": -5.9953403
}
},
"relationships": {
"locality": {
"data": {
"id": "1",
"type": "locality"
}
}
}
},
"included": [
{
"id": "1",
"type": "locality",
"attributes": {
"name": "Seville",
"latitude": 37.3886303,
"longitude": -5.9953403,
"slug": "seville"
},
"relationships": {
"country": {
"data": {
"id": "168",
"type": "country"
}
}
}
},
{
"id": "168",
"type": "country",
"attributes": {
"name": "Spain",
"slug": "spain",
"iso_3166_1_alpha2": "ES",
"iso_3166_1_alpha3": "ESP",
"iso_3166_1_numeric": "724"
},
"relationships": {
"localities": {
"data": [
{
"id": "1",
"type": "locality"
},
{
"id": "2",
"type": "locality"
},
{
"id": "3",
"type": "locality"
},
{
"id": "4",
"type": "locality"
},
{
"id": "5",
"type": "locality"
},
{
"id": "6",
"type": "locality"
}
]
},
"attractions": {
"data": [
{
"id": "1",
"type": "attraction"
}
]
}
}
}
]
}
Is there a way to only include just one attribute (i.e. name of Country) in the Attraction JSON, instead of the whole object? (Attraction is nested two levels below Country)
Thank you very much.
You need to create multiple serializers that work together to achieve this.
class AttractionSerializer
include FastJsonapi::ObjectSerializer
attributes :attraction_attr_1, :attraction_attr_2, etc.
belongs_to :locality, serializer: AttractionLocalitySerializer
end
class AttractionLocalitySerializer
include FastJsonapi::ObjectSerializer
attributes :name
belongs_to :country, serializer: AttractionCountrySerializer
end
class AttractionCountrySerializer
include FastJsonapi::ObjectSerializer
attributes :name
end
I am creating an avro schema for a JSON payload that appear to have an array of multiple objects. I'm not sure exactly how to represent this in the schema. The key in question is content:
{
"id": "channel-id",
"name": "My Channel with a New Title",
"description": "Herpy me derpy merpus herpsum ner berp berps derp ter tee",
"privacyLevel": "<private|org>",
"planId": "some-plan-id",
"owner": "a-user-handle",
"curators": [
"user-handle-1",
"user-handle-2"
],
"members": 5,
"content": [
{
"id": "docker",
"slug": "docker",
"index": 1,
"type": "path"
},
{
"id": "such-linkage",
"slug": "such-linkage",
"index": 2,
"type": "external-link",
"details": {
"url": "http://some-dank-link.com",
"title": "My Dank Link",
"contentType": "External Link",
"level": "Beginner",
"duration": "PT34293H33M9S"
}
},
{
"id": "21f1e812-b10a-40df-8b52-3a1d05fc215c",
"slug": "windows-azure-storage-in-depth",
"index": 3,
"type": "course"
},
{
"id": "7c346c05-6416-42dd-80b2-d5e758de7926",
"slug": "7c346c05-6416-42dd-80b2-d5e758de7926",
"index": 4,
"type": "project"
}
],
"imageUrls": ["https://url/to/an/image", "https://url/to/another/image"],
"analyticsEnabled": true,
"orgDiscoverable": false,
"createdDate": "2015-12-31T01:23:45+00:00",
"archiveDate": "2015-12-31T01:23:45+00:00",
"messagePublishedAt": "2015-12-31T01:23:45+00:00"
}
If you are asking if it is possible create an array with different kind of records, it is. Avro support this through union. it would looks like .
{
"name": "myRecord",
"type":"record",
"fields":[
{
"name":"myArrayWithMultiplesTypes",
"type":{
"type": "array",
"items":[
{
"name":"typeOne",
"type":"record",
"fields":[
{"name":"name", "type":"string"}
]
},
{
"name":"typeTwo",
"type":"record",
"fields":[
{"name":"id", "type":"int"}
]
}
]
}
}
]
}
If you already have the records defined previously, then it could look like this:
{
"name": "mulitplePossibleTypes",
"type": [
"null",
{
"type": "array",
"items": [
"com.xyz.kola.cloud.events.itemmanager.Part",
"com.xyz.kola.cloud.events.itemmanager.Document",
"com.xyz.kola.cloud.events.itemmanager.DigitalModel",
"com.xyz.kola.cloud.events.itemmanager.Interface"
]
}
]
},
I want to fetch only a particular category that belongs to an email from Microsoft Graph / Outlook endpoint. But is gives me all the categories which are present in associated email.
[https://graph.microsoft.com/beta/me/outlook/masterCategories/?$filter = displayName eq 'Red category']
Above link is my query to Microsoft Graph API and I get the following result
{
"#odata.context": "https://graph.microsoft.com/beta/$metadata#users('1e69674d-b0b3-404e-ae2d-a758569ce83c')/outlook/masterCategories",
"value": [
{
"id": "347a7dcc-6c61-4c93-85a5-eb75f973a77f",
"displayName": "Red category",
"color": "preset0"
},
{
"id": "643d45c3-aecb-4fbb-8254-c2520f01cf20",
"displayName": "Orange category",
"color": "preset1"
},
{
"id": "d06a692a-9406-4052-9b1e-bc7ae293a4e4",
"displayName": "Yellow category",
"color": "preset3"
},
{
"id": "8c3e842d-427f-4480-8459-e3e4e785fa85",
"displayName": "Green category",
"color": "preset4"
},
{
"id": "11502440-1912-4de1-afad-c2209178219d",
"displayName": "Blue category",
"color": "preset7"
},
{
"id": "f3f1b1ca-b319-4951-9eeb-954a169e3d71",
"displayName": "Purple category",
"color": "preset8"
},
{
"id": "1fc2506b-2676-447c-bfa3-44a3a7a2dc2d",
"displayName": "Important",
"color": "preset14"
},
{
"id": "8926f11d-23ba-4804-ace7-8ae349f390a6",
"displayName": "Caution",
"color": "preset16"
},
{
"id": "60434e45-effa-40d7-b753-705d59ef3440",
"displayName": "Star",
"color": "preset2"
}
]
}
Any ways of filtering the categories through properties like displayName ?
Based on official guideline, it supports {id} to filter.
https://graph.microsoft.com/beta/me/outlook/masterCategories/8cefb2b7-8f81-47e3-b6d3-a8e2dd4ac42a
https://developer.microsoft.com/en-us/graph/docs/api-reference/beta/api/outlookcategory_get
The /me/ normally doesn't return filters for me very well.
Try calling
/users/{id}/outlook/masterCategories?filter=displayName eq 'Red Category'