Rules for real time database chat when using an external database - flutter

I am trying to secure my real time db. I have the following database structure:
{
"chats": {
"-NMhLlfSU-HYmjmXBzmH": {
"lastMessage": "",
"lastSender": "",
"seen": true,
"timestamp": 1674724449157
},
"members": {
"-NMhLlfSU-HYmjmXBzmH": {
"63cc6d925b51cb7a423393cc": true,
"63d240635b51cb7a423397d5": true
},
},
"users": {
"63cc6d925b51cb7a423393cc": {
"city": "Ituzaingó, Buenos Aires Province, Argentina",
"contacts": {
"63d240635b51cb7a423397d5": true
},
"name": "Joaquin varela",
"picture": "https://cdn.pixabay.com/photo/2015/10/05/22/37/blank-profile-picture-973460_1280.png"
},
"63d240635b51cb7a423397d5": {
"city": "Madrid",
"contacts": {
"63cc6d925b51cb7a423393cc": true
},
"name": "Test Test",
"picture": "https://cdn.pixabay.com/photo/2015/10/05/22/37/blank-profile-picture-973460_1280.png"
},
}
I am trying to implement the rules for it. The only problem is, my auth.uid is not the same as my user_id
Is there any way to secure my database? Maybe passing some user_id argument but I don't know how.
I hope you can help me. Thanks in advance!

Related

How to use embedsMany in laravel to get all attributes? Only foreign key is returning

Hello Good Developers,
I am trying to implement embedsMany relationship of jenssegers/laravel-mongodb
I have two collections:
ProfileSection - {
"_id": "5c865ea4257db43fe4007331",
"general_name": "MY_PROFILE",
"type": "public",
"points": 100,
"status": 1,
"translated": [
{
"con_lang": "US-EN",
"country_code": "US",
"language": "EN",
"text": "My Profile",
"description": "My Profile"
},
...
],
"updated_at": "2019-03-11T13:12:04.000Z",
"created_at": "2019-03-11T13:12:04.000Z"
}
Profile Questions - {
"_id": "5c865ea3257db43fe40072b2",
"id": "STANDARD_EDUCATION",
"general_name": "STANDARD_EDUCATION",
"country_code": "US",
"order": 1,
"profile_section_id": "5c865ea4257db43fe4007331",
"profile_section": "My Profile",
"translated": [
{
"con_lang": "US-EN",
"text": "What is the highest level of education you have completed?",
"hint": null,
"mapping": {},
"answers": [
{
"precode": "1",
"text": "3rd Grade or less",
"mapping": {}
}
]
},
{...}
],
"updated_at": "2019-03-11T13:12:03.000Z",
"created_at": "2019-03-11T13:12:03.000Z"
}
In ProfileSection I have added
public function questions()
{
return $this->embedsMany(ProfilerQuestions::class, '_id', 'profile_section_id');
}
If I execute ProfileSection::find('5c865ea4257db43fe4007331')->questions
It returns me Profile Questions Object with only one attribute: 5c865ea4257db43fe4007331 i.e ObjectId of Profile Section
I tried using ->with('questions) before accessing questions object
like this
but it's not working
I don't understand what's the issue will definitely need some help.

Google Action / Dialogflow : how to ask for geolocation

I'm trying to implement a simple app for Google Assistant.
All works fine, but now I have a problem with the "permission" helper :
https://developers.google.com/actions/assistant/helpers#helper_intents
I have an intent connected with webhook to my java application. When an user types a sentence similar to "near to me", I want to ask to him his location and then use lat/lon to perform a search.
es: Brazilian restaurant near to me
my intent "searchRestaurant" is fired
I receive the webhook request and I parse it
if I find a parameter that is connected to a sentence like "near to me", so instead to response with a "Card" or a "List" I return a JSON that represent the helper request :
{
"conversationToken": "[]",
"expectUserResponse": true,
"expectedInputs": [
{
"inputPrompt": {
"initialPrompts": [
{
"textToSpeech": "PLACEHOLDER_FOR_PERMISSION"
}
],
"noInputPrompts": []
},
"possibileIntents": [
{
"intent": "actions.intent.PERMISSION",
"inputValueData": {
"#type": "type.googleapis.com/google.actions.v2.PermissionValueSpec",
"optContext": "Posso accedere alla tua posizione?",
"permission": [
"NAME",
"DEVICE_PRECISE_LOCATION"
]
}
}
]
}
]
}
but something seems to be wrong, and I receive an error:
"{\n \"responseMetadata\": {\n \"status\": {\n \"code\": 10,\n \"message\": \"Failed to parse Dialogflow response into AppResponse because of empty speech response\",\n \"details\": [{\n \"#type\": \"type.googleapis.com/google.protobuf.Value\",\n \"value\": \"{\\"id\\":\\"1cc45c5e-c398-4ea7-98a5-408f31ce142d\\",\\"timestamp\\":\\"2018-08-02T14:45:05.752Z\\",\\"lang\\":\\"it\\",\\"result\\":{},\\"alternateResult\\":{},\\"status\\":{\\"code\\":206,\\"errorType\\":\\"partial_content\\",\\"errorDetails\\":\\"Webhook call failed. Error: Failed to parse webhook JSON response: Cannot find field: conversationToken in message google.cloud.dialogflow.v2.WebhookResponse.\\"},\\"sessionId\\":\\"1533221100163\\"}\"\n }]\n }\n }\n}"
The "conversationToken" is filled, so I don't understand the error message.
Maybe I'm trying to perform the operation in a wrong way.
So, which is the correct way to call this helper?
--> I've created a second intent "askGeolocation" that have "actions_intent_PERMISSION" as "Event", and ... if I understand correctly the documentation, should be trigger if the request for helper is correct.
How can I get this working?
UPDATE :
I find some example of the json response for ask permission and seems that it should be different from the one above that i'm using :
https://github.com/dialogflow/fulfillment-webhook-json/blob/master/responses/v2/ActionsOnGoogle/AskForPermission.json
{
"payload": {
"google": {
"expectUserResponse": true,
"systemIntent": {
"intent": "actions.intent.PERMISSION",
"data": {
"#type": "type.googleapis.com/google.actions.v2.PermissionValueSpec",
"optContext": "To deliver your order",
"permissions": [
"NAME",
"DEVICE_PRECISE_LOCATION"
]
}
}
}
}
}
so, i've implemented it and now the response seems to be good (no more error on parsing it), but i still receive an error on it validation :
UnparseableJsonResponse
API Version 2: Failed to parse JSON response string with 'INVALID_ARGUMENT' error: "permission: Cannot find field."
so, a problem still persist.
Anyone know the cause?
Thanks
After some tests i found the problem.
I was returning a wrong json repsonse with "permission" instead of "permissions":
"permission**s**": [
"NAME",
"DEVICE_PRECISE_LOCATION"
]
So the steps to ask for location are correct. I report them here as a little tutorial in order to help who is facing on it for the first time:
1) In DialogFlow, add some logic to your Intent, in order to understand when is ok to ask to user his location. In my case, i've added a "parameter" that identify sentences like "nearby" and so on.
2) When my Intent is fired i receive to my java application a request like this :
...
"queryResult": {
"queryText": "ristorante argentino qui vicino",
"action": "bycategory",
"parameters": {
"askgeolocation": "qui vicino",
"TipoRistorante": ["ristorante", "argentino"]
},
...
3) If "askgeolocation" parameter is filled, instead to return a "simple message" o other type of message, i return a json for ask the permission to geolocation :
{
"payload": {
"google": {
"expectUserResponse": true,
"systemIntent": {
"intent": "actions.intent.PERMISSION",
"data": {
"#type": "type.googleapis.com/google.actions.v2.PermissionValueSpec",
"optContext": "To deliver your order",
"permissions": [
"NAME",
"DEVICE_PRECISE_LOCATION"
]
}
}
}
}
}
4) You MUST have a second Intent that is configured with "actions_intent_PERMISSION " event :
No training phrases
No Action and params
No Responses
But with Fulfillment active :
5) Once your response arrive to Google Assistant this is the message that appear :
6) Now, if user answer "ok" you receive this json on your webhook :
{
"responseId": "32cf46cf-80d8-xxxxxxxxxxxxxxxxxxxxx",
"queryResult": {
"queryText": "actions_intent_PERMISSION",
"action": "geoposition",
"parameters": {
},
"allRequiredParamsPresent": true,
"fulfillmentMessages": [{
"text": {
"text": [""]
}
}],
"outputContexts": [{
"name": "projects/xxxxxxxxxxxxxxxxxxxxx"
}, {
"name": "projects/xxxxxxxxxxxxxxxxxxxxx",
"parameters": {
"PERMISSION": true
}
}, {
"name": "projects/xxxxxxxxxxxxxxxxxxxxx"
}, {
"name": "projects/xxxxxxxxxxxxxxxxxxxxx"
}, {
"name": "projects/xxxxxxxxxxxxxxxxxxxxx"
}, {
"name": "projects/xxxxxxxxxxxxxxxxxxxxx"
}],
"intent": {
"name": "projects/xxxxxxxxxxxxxxxxxxxxx",
"displayName": "geoposition"
},
"intentDetectionConfidence": 1.0,
"languageCode": "it"
},
"originalDetectIntentRequest": {
"source": "google",
"version": "2",
"payload": {
"isInSandbox": true,
"surface": {
"capabilities": [{
"name": "actions.capability.MEDIA_RESPONSE_AUDIO"
}, {
"name": "actions.capability.SCREEN_OUTPUT"
}, {
"name": "actions.capability.AUDIO_OUTPUT"
}, {
"name": "actions.capability.WEB_BROWSER"
}]
},
"requestType": "SIMULATOR",
"inputs": [{
"rawInputs": [{
"inputType": "KEYBOARD"
}],
"arguments": [{
"textValue": "true",
"name": "PERMISSION",
"boolValue": true
}],
"intent": "actions.intent.PERMISSION"
}],
"user": {
"lastSeen": "2018-08-03T08:55:20Z",
"permissions": ["NAME", "DEVICE_PRECISE_LOCATION"],
"profile": {
"displayName": ".... full name of the user ...",
"givenName": "... name ...",
"familyName": "... surname ..."
},
"locale": "it-IT",
"userId": "xxxxxxxxxxxxxxxxxxxxx"
},
"device": {
"location": {
"coordinates": {
"latitude": 45.xxxxxx,
"longitude": 9.xxxxxx
}
}
},
"conversation": {
"conversationId": "xxxxxxxxxxxxxxxxxxxxx",
"type": "ACTIVE",
"conversationToken": "[]"
},
"availableSurfaces": [{
"capabilities": [{
"name": "actions.capability.SCREEN_OUTPUT"
}, {
"name": "actions.capability.AUDIO_OUTPUT"
}, {
"name": "actions.capability.WEB_BROWSER"
}]
}]
}
},
"session": "projects/xxxxxxxxxxxxxxxxxxxxx"
}
that contains, name/surname and latitude/longitude. This information can be saved in your application, in order to not perform again this steps.
I hope this helps.
Davide
In your intent, you can ask for a parameter with a custom Entity. This you can do like this:
entity you can define as "near"
put all the synonyms for near for which you want to trigger location permission in this entity
do not mark this parameter as "required"
do not put any prompt
in the training phrases, add some phrases with this parameter
in your webhook, keep a check on the parameter, if present ask for permission if not continue.
add a permission event to another intent
do your post permission processing in that intent
Entity
Intent
I hope you get it.
There are samples on this topic specifically that guide you through exactly what's needed for requesting permissions in Node and Java.
Note: There are helper intents samples available in Node and Java as well.

HTTP requests are tampered by other HTTP requests, with golang and standard library

cat main.go:
```
package main
import (
"encoding/json"
"log"
"net"
"net/http"
"net/http/fcgi"
"os"
)
func main() {
//setup the config
configFile := "config.json"
fd, err := os.Open(configFile)
if err != nil {
log.Fatalf("Can't open config file: %v", configFile)
}
CFG := config{}
err = json.NewDecoder(fd).Decode(&CFG)
if err != nil {
log.Fatalf("parse config error: %v", err)
}
//init DB connection
db.InitConnectionInfo(CFG.Database.Host, CFG.Database.Port, CFG.Database.Database, CFG.Database.Username, CFG.Database.Password)
//register HTTP handler
sessionHandler := &handlers.SessionHandler{}
http.Handle("/sessions", sessionHandler)
http.Handle("/sessions/", sessionHandler)
userHandler := &handlers.UserHandler{
Facebook: &oa.OAuth{AppId: CFG.Facebook.Key, Secret: CFG.Facebook.Secret},
Sina: &oa.OAuth{AppId: CFG.Sina.Key, Secret: CFG.Sina.Secret},
Google: &oa.OAuth{AppId: CFG.Google.Key, Secret: CFG.Google.Secret},
Tencent: &oa.OAuth{AppId: CFG.Tencent.Key, Secret: CFG.Tencent.Secret},
Mixpanel: &hu.Share{Token: CFG.Mixpanel.Token},
FacebookShare: &hu.Share{Token: CFG.Facebook.Token},
SinaShare: &hu.Share{Token: CFG.Sina.Token},
GoogleShare: &hu.Share{Token: CFG.Google.Token},
TencentShare: &hu.Share{Token: CFG.Tencent.Token},
}
http.Handle("/users", userHandler)
http.Handle("/users/", userHandler)
//and so on ...
//run server
log.Println("start listen: ", CFG.FcgiAddr)
l, _ := net.Listen("tcp", CFG.FcgiAddr)
log.Fatalf("server error is %v", fcgi.Serve(l, nil))
//##select {}
log.Println("end listen")
}
```
build it and deploy behind nginx.
then client query /users/1234567/places, /users/1234567, and so on...
get the response is {blank data}, {normal user(1234567) data} or {normal user(1234567) data}, {normal user(1234567) data}.
same prefix of query, and same handler, looks like it is overload the response by subsequent HTTP request.
How can I do it?
May need me to give an example of a response:
correct response is :
{
"meta": {
"code": 200,
"text": "OK"
},
"data": {
"count": 21,
"place-tag-maps": [{
"id": "95842310160384",
"place-id": "95551731663150",
"tag-id": "95551579750669",
"ct": "2014-07-01T09:07:28Z"
}, {
"id": "95842310160385",
"place-id": "95551731663150",
"tag-id": "95551579750694",
"ct": "2015-01-15T17:41:23Z"
}, {
"id": "96262389694470",
"place-id": "95551731663150",
"tag-id": "95910120456455",
"ct": "2016-07-18T13:11:39Z"
}, ...],
"places": [{
"id": "95551731663150",
"name": "Kam Fung Restaurant",
"address": "G/F, 41 Spring Garden Ln",
"coordinate": {
"latitude": 22.275576,
"longitude": 114.172582
},
"telephone": "+852 2572 0526",
"city-id": "95530516807703",
"city": "Hong Kong",
"country": "Hong Kong",
"type": "4sq",
"ref-id": "4b1613f8f964a520cdb623e3",
"ct": "2016-02-23T07:42:43.565489Z",
"mt": "2017-02-22T09:35:48.302929Z",
"rating": 7.5,
"stats": {
"foursquare": {
"count": 111,
"value": 7.5
},
"spottly": {
"save-count": 12
}
},
"permanent-close": false,
"price": ""
}, ...],
"posts": [{
"collection-id": "95551746474003",
"coordinate": {
"latitude": 22.275576,
"longitude": 114.172582
},
"ct": "2017-02-22T09:35:47Z",
"facebook-tag-users": [],
"id": "97501586849795",
"medias": [],
"message": "",
"mt": "2017-02-22T09:35:47Z",
"owner-id": "96527264645120",
"place-id": "95551731663150",
"share-to": [],
"star": 5,
"status": "Done",
"tags": []
}, ...],
"users": [{
"id": "95551581323446",
"uid": "hk_epicurus",
"uid-ignore-case": "hk_epicurus",
"name": "Hk Epicurus",
"head": "https://d278wa0j9nq2mp.cloudfront.net/uploader/54aa335ddf4e63450002919a.jpeg",
"site": "www.hkepicurus.com",
"location": "Hong Kong",
"description": "Hong Kong Food \u0026 Travel Bear.\nGrew up in Aust, Malaysia, Tokyo \u0026 HK. \nInstagram: EpicurusHongKong\nFacebook, Spottly \u0026 Twitter: HK Epicurus \n微博: 香港美食-伊比\nFacebook Fans Page: http://on.fb.me/1qDyiIk",
"ct": "2013-10-13T19:12:41Z",
"mt": "2015-11-08T15:22:45Z"
}, ...]
}
}
and
{
"meta": {
"code": 200,
"text": "OK"
},
"data": {
"friends": [{
"id": "97331335725056",
"from-id": "97273770803200",
"to-id": "96527264645120",
"ct": "2017-01-23T07:58:41Z"
}],
"user": {
"ct": "2013-04-30T23:30:05Z",
"description": "Founder and Chief Everything Officer of Spottly. Loves to eat. Have a really bad memory. Wants to remember the best places and make travel research better",
"followers": {
"count": 41291
},
"followings": {
"count": 322
},
"head": "https://d278wa0j9nq2mp.cloudfront.net/uploader/525ffac8df4e6347870145ef.jpeg",
"id": "96527264645120",
"location": "Vancouver | Hong Kong | Beijing ",
"mt": "2015-10-27T09:47:12Z",
"name": "Edwyn Chan",
"site": "http://spottly.com/edwyn",
"uid": "edwyn",
"uid-ignore-case": "edwyn"
}
}
}
but mistake response is
{
"meta": {
"code": 200,
"text": "OK"
}
}
and
{
"meta": {
"code": 200,
"text": "OK"
},
"data": {
"friends": [{
"id": "97331335725056",
"from-id": "97273770803200",
"to-id": "96527264645120",
"ct": "2017-01-23T07:58:41Z"
}],
"user": {
"ct": "2013-04-30T23:30:05Z",
"description": "Founder and Chief Everything Officer of Spottly. Loves to eat. Have a really bad memory. Wants to remember the best places and make travel research better",
"followers": {
"count": 41291
},
"followings": {
"count": 322
},
"head": "https://d278wa0j9nq2mp.cloudfront.net/uploader/525ffac8df4e6347870145ef.jpeg",
"id": "96527264645120",
"location": "Vancouver | Hong Kong | Beijing ",
"mt": "2015-10-27T09:47:12Z",
"name": "Edwyn Chan",
"site": "http://spottly.com/edwyn",
"uid": "edwyn",
"uid-ignore-case": "edwyn"
}
}
}
the first response is error. or it's same as the second response.
sequence request is correct response, parallel request is incorrect response.
problem resolved。
the basic reason is this case:
var x = &{...} //init value
fillX(..., x) //fill the fields of x pointer
//here the fields of x pointer is not same to inner of fillX func
so, change to
var x = &{...}
x = fullX(..., x)
the problem resolved.
but why go pointer is the behavior?
Finally, this problem resolved.
Because the http.Handle register path-pattern and handler pair, the handler is construct by register time only-once, not for any request of path-pattern.
if record info within handler, It will been change by after request.

Jasper Report with RestAPI

I have a report on JasperServer(5.6) which accepts few parameters. I edit few settings on the Output Options tab and enter emails which i would like to sent to on Notifications tab. The report gets generated successfully and an email is sent out perfectly.
I wish to use the Rest API of JasperServer to pass on my input options and to schedule and email the report. I went through there documentation http://community.jaspersoft.com/documentation/jasperreports-server-web-services-guide/v56/rest-v2-report-services but couldn't understand how to use the rest api.
Here is the properties of my report on the jasper server
Can someone help me out how to schedule my report.
Maybe it's can help you: jasperserver rest java client.
This is a REST client for Jasperserver.
I guess, i have figured out the way to schedule a job on jasper server. Details can be found here
http://community.jaspersoft.com/documentation/tibco-jasperreports-server-web-services-guide/v62/scheduling-report
But as an example here it is (call it with PUT method)
http://localhost:8080/jasperserver/rest_v2/jobs
and in the body define the job structure
{
"id": 3819,
"version": 2,
"username": "jasperadmin",
"label": "publisher_123_report",
"description": "",
"creationDate": "2015-12-30T02:02:40.382+03:00",
"trigger": {
"simpleTrigger": {
"id": "1770",
"misfireInstruction": "0",
"startDate": "2015-12-20T00:00:00+11:00",
"startType": "2",
"timezone": "Australia/Victoria",
"version": "0",
"occurrenceCount": "1"
}
},
"source": {
"reportUnitURI": "/Reports/Prod/test_automated_report_v14",
"parameters": {
"parameterValues": {
"PublisherId" : "20",
"MonthEnd" : "2015-02-01",
"MonthStart" : "2015-03-20",
"email" : "admin#admin.com",
"CountryCode" : "560"
}
}
},
"baseOutputFilename": "publisher_124_automated_report",
"outputLocale": "",
"mailNotification": {
"subject": "publisher monthly report" ,
"toAddresses": {
"address": ["address1To#add.com", "address2To#add.com"]
},
"ccAddresses": {
"address": ["address1cc#add.com", "address2cc#add.com"]
},
"bccAddresses": {
"address": ["address1bcc#add.com", "address2bcc#add.com"]
},
"includingStackTraceWhenJobFails" : false,
"resultSendType" : "SEND_EMBED",
"skipEmptyReports" : true,
"skipNotificationWhenJobFails" : false
},
"alert": {
"id": 0,
"version": -1,
"recipient": "OWNER_AND_ADMIN",
"toAddresses": {
"address": ["address1#add.com", "address2#add.com"]
},
"jobState": "FAIL_ONLY",
"messageText": "Success",
"messageTextWhenJobFails": "Failure",
"subject": "Notification Subject",
"includingStackTrace": true,
"includingReportJobInfo": true,
"jobState" : "ALL"
},
"outputTimeZone": "Australia/Melbourne",
"repositoryDestination": {
"id": 3817,
"version": 0,
"folderURI": "/Reports/Prod",
"sequentialFilenames": false,
"overwriteFiles": false,
"outputDescription": "",
"timestampPattern": null,
"saveToRepository": true,
"defaultReportOutputFolderURI": null,
"usingDefaultReportOutputFolderURI": false,
"outputLocalFolder": null,
"outputFTPInfo": {
"userName": null,
"password": null,
"folderPath": null,
"serverName": null
}
},
"outputFormats": {
"outputFormat": ["HTML"]
}
}
More options can be supplied while the creating job.

How can I query an indexed object list in mongodb?

I have some documents in the "company" collection structured this way :
[
{
"company_name": "Company 1",
"contacts": {
"main": {
"email": "main#company1.com",
"name": "Mainuser"
},
"store1": {
"email": "store1#company1.com",
"name": "Store1 user"
},
"store2": {
"email": "store2#company1.com",
"name": "Store2 user"
}
}
},
{
"company_name": "Company 2",
"contacts": {
"main": {
"email": "main#company2.com",
"name": "Mainuser"
},
"store1": {
"email": "store1#company2.com",
"name": "Store1 user"
},
"store2": {
"email": "store2#company2.com",
"name": "Store2 user"
}
}
}
]
I'm trying to retrieve the doc that have store1#company2.com as a contact but cannot find how to query a specific value of a specific propertie of an "indexed" list of objects.
My feeling is that the contacts lists should not not be indexed resulting in the following structure :
{
"company_name": "Company 1",
"contacts": [
{
"email": "main#company1.com",
"name": "Mainuser",
"label": "main"
},
{
"email": "store1#company1.com",
"name": "Store1 user",
"label": "store1"
},
{
"email": "store2#company1.com",
"name": "Store2 user",
"label": "store2"
}
]
}
This way I can retrieve matching documents through the following request :
db.company.find({"contacts.email":"main#company1.com"})
But is there anyway to do a similar request on document using the previous structure ?
Thanks a lot for your answers!
P.S. : same question for documents structured this way :
{
"company_name": "Company 1",
"contacts": {
"0": {
"email": "main#company1.com",
"name": "Mainuser"
},
"4": {
"email": "store1#company1.com",
"name": "Store1 user"
},
"1": {
"email": "store2#company1.com",
"name": "Store2 user"
}
}
}
Short answer: yes, they can be queried but it's probably not what you want and it's not going to be really efficient.
The document structure in the first and third block is basically the same - you have an embedded document. The only difference between are the name of the keys in the contacts object.
To query document with that kind of structure you will have to do a query like this:
db.company.find({ $or : [
{"contacts.main.email":"main#company1.com"},
{"contacts.store1.email":"main#company1.com"},
{"contacts.store2.email":"main#company1.com"}
]});
This query will not be efficient, especially if you have a lot of keys in the contacts object. Also, creating a query will be unnecessarily difficult and error prone.
The second document structure, with an array of embedded objects, is optimal. You can create a multikey index on the contacts array which will make your query faster. The bonus is that you can use a short and simple query.
I think the easiest is really to shape your document using the structure describe in your 2nd example : (I have not fixed the JSON)
{
"company_name": "Company 1",
"contacts":{[
{"email":"main#company1.com","name":"Mainuser", "label": "main", ...}
{"email":"store1#company1.com","name":"Store1 user", "label": "store1",...}
{"email":"store2#company1.com","name":"Store2 user", "label": "store2",...}
]}
}
like that you can easily query on email independently of the "label".
So if you really want to use the other structure, (but you need to fix the JSON too) you will have to write more complex code/aggregation pipeline, since we do not know the name and number of attributes when querying the system. Theses structures are also probably hard to use by the developers independently of MongoDB queries.
Since it was not clear let me show what I have in mind
db.company.save(
{
"company_name": "Company 1",
"contacts":[
{"email":"main#company1.com","name":"Mainuser", "label": "main"},
{"email":"store1#company1.com","name":"Store1 user", "label": "store1"},
{"email":"store2#company1.com","name":"Store2 user", "label": "store2"}
]
}
);
db.company.save(
{
"company_name": "Company 2",
"contacts":[
{"email":"main#company2.com","name":"Mainuser", "label": "main"},
{"email":"store1#company2.com","name":"Store1 user", "label": "store1"},
{"email":"store2#company2.com","name":"Store2 user", "label": "store2"}
]
}
);
db.company.ensureIndex( { "contacts.email" : 1 } );
db.company.find( { "contacts.email" : "store1#company2.com" } );
This allows you to store many emails, and query with an index.