MongoDB URI ასე გამოიყურება: mongodb://[user:password@]host1[:port1][,host2[:port2],...][/database][?options]. თუ არაფერს მიუთითებ, ყველა ოფიციალური ხელსაწყო იყენებს mongodb://localhost:27017-ს. mongodb+srv:// ფორმა იღებს ზუსტად ერთ ჰოსტის სახელს და არანაირ პორტს, ჰოსტების რეალურ სიას DNS-ს ეკითხება და TLS-ს ავტომატურად რთავს. მძიმეებით გამოყოფილი რამდენიმე ჰოსტი replica set-ის ან mongos როუტერების საწყისი სიაა და არა სარეზერვო სერვერების ჩამონათვალი. დრაივერი დაუკავშირდება იმ წევრს, რომელსაც თავად ჩათვლის სწორად - სწორედ ამიტომ არსებობს directConnection.
ფორმატი სულ ეს არის. ამ სახელმძღვანელოს დანარჩენი ნაწილი განმარტავს, რას აკეთებს თითოეული ელემენტი პრაქტიკაში: ნაგულისხმევ მნიშვნელობებს, +srv-ის უკან მდგარ DNS ჩანაწერებს, როგორ ექცევა დრაივერი ერთზე მეტ ჰოსტს, რომელი პარამეტრები ცვლის ქცევას და სად იწერება სტრიქონი PyMongo-ში, Node-ის დრაივერში, mongosh-ში, .NET-ის კონფიგურაციის ფაილებსა და Compass-ში. URI-ის ნაწილების და პაროლის პროცენტული კოდირების უფრო მშვიდ ახსნას იპოვი აქ: MongoDB connection strings. თუ URI გაქვს და სერვერი გპასუხობს Authentication failed-ით, გადადი authSource-ის პრობლემების გზამკვლევზე; ამ სტატიაში არც ერთს არ გავიმეორებ.
ფორმატი ნაწილ-ნაწილ#
mongodb:// schemeshopapp:pw@ credentials (optional)db1.example.net:27017,db2.example.net:27017 host list/shop default database (optional)?replicaSet=rs0&appName=api options (optional)ცარიელი ადგილების გარეშე რომ გავაერთიანოთ, მივიღებთ: mongodb://shopapp:pw@db1.example.net:27017,db2.example.net:27017/shop?replicaSet=rs0&appName=api.
წესები, რომლებიც ადვილად ავიწყდებათ:
- პორტი არასავალდებულოა და ყველა ჰოსტისთვის, რომელსაც პორტი არ აქვს, ნაგულისხმევია
27017.mongodb://db.example.netდაmongodb://db.example.net:27017ერთი და იგივეა. - IPv6 მისამართი კვადრატულ ფრჩხილებში იწერება:
mongodb://[2001:db8::10]:27017. ფრჩხილების გარეშე მისამართის ორწერტილები პორტის გამყოფად აღიქმება და URI ვერ გაიშიფრება. - Unix domain socket იწერება ჰოსტის ადგილას, პროცენტულად დაკოდირებული გზის სახით:
mongodb://%2Ftmp%2Fmongodb-27017.sock.mongodამ socket-ს Linux-სა და macOS-ზე ნაგულისხმევად ქმნის და ეს მოსახერხებელი გზაა იმავე მანქანიდან დასაკავშირებლად, TCP პორტის გახსნის გარეშე. ?-მდე ხაზი აუცილებელია, როცა პარამეტრები გაქვს.mongodb://host:27017/?tls=trueსწორია; დრაივერები განსხვავებულად იქცევიან, როცა ხაზი აკლია, ამიტომ ამაზე ნუ დაეყრდნობი.- პარამეტრების სახელებში რეგისტრი არ ითვალისწინება (
authsourceდაauthSourceერთია), მნიშვნელობებში კი ითვალისწინება, ხოლო ლოგიკური მნიშვნელობები პატარა ასოებით დაწერილიtrueდაfalseსტრიქონებია. ზოგი დრაივერი1-ს,yes-ს და მსგავსებსაც იღებს, მაგრამ ეს ყველგან არ მუშაობს. - პარამეტრები
&-ით ერთდება. რამდენიმე მათგანი შეიძლება განმეორდეს, მაგალითადreadPreferenceTags; დანარჩენებისთვის ბოლო მნიშვნელობა იმარჯვებს ან დრაივერი შეცდომას აბრუნებს, დრაივერის მიხედვით.
ნაგულისხმევი: localhost:27017
mongodb://localhost:27017 არის სტრიქონი, რომელიც ყველა გაკვეთილშია, Compass-ის ახალი კავშირის ეკრანის ნაგულისხმევი მნიშვნელობა და ის, რასაც PyMongo-ში არგუმენტების გარეშე გამოძახებული MongoClient() უკავშირდება. მას ერთი ცნობილი მახე აქვს. Node.js 17-სა და უფრო ახალ ვერსიებში localhost შეიძლება ჯერ IPv6 მისამართზე ::1 გადაიშალოს, ნაგულისხმევი mongod კი მხოლოდ 127.0.0.1-ზე უსმენს. შედეგი არის connect ECONNREFUSED ::1:27017 სრულიად ჯანსაღად მომუშავე სერვერზე. Node-ის ახალი ვერსიები ორივე მისამართის ოჯახს ცდის და ეს ნაკლებად ხდება, მაგრამ საიმედო გამოსავალია ლოკალურ URI-ებში localhost-ის ნაცვლად 127.0.0.1 დაწერო ან mongod.conf-ში net.bindIp-ს ::1 დაუმატო.
mongosh არგუმენტების გარეშეც არ იყენებს უბრალო ნაგულისხმევს. ის უკავშირდება mongodb://127.0.0.1:27017/?directConnection=true&serverSelectionTimeoutMS=2000-ს და ამ სტრიქონს პირველივე ხაზზე ბეჭდავს, რაც კარგი მინიშნებაა, რომელი პარამეტრების დაყენებაა ღირს, როცა ყოველთვის მხოლოდ ერთ ლოკალურ სერვერთან მუშაობ.
რომელ ბაზას ასახელებს გზა
/database ნაწილი კლიენტის ნაგულისხმევი ბაზაა და authSource-ის ნაგულისხმევიც, როცა ეს პარამეტრი არ არის მითითებული. ის არაფერს ზღუდავს: /shop-ით დაკავშირებულ კლიენტს მაინც შეუძლია client["reports"] გახსნას, თუ მომხმარებელს ამის უფლება აქვს. თუ გზას ცარიელს დატოვებ, ნაგულისხმევი ბაზა დრაივერზეა დამოკიდებული (ხშირად test ან საერთოდ არაფერი), authSource კი admin-ზე გადადის. სწორედ ეს მეორე ნაგულისხმევი არის ავთენტიფიკაციასთან დაკავშირებული უმეტესი დაბნეულობის წყარო, ხოლო მომხმარებლებისა და როლების გზამკვლევი განმარტავს, რატომ ცხოვრობენ მომხმარებლები იქ, სადაც ცხოვრობენ.
mongodb+srv:// და მის უკან მდგარი DNS ჩანაწერები#
საწყისი სიის URI (mongodb+srv://) ჰოსტების სიას ერთი DNS სახელით ცვლის. როცა დრაივერი მას ხედავს, ერთი კავშირის გახსნამდეც ორ მოთხოვნას აკეთებს.
SRV ჩანაწერი მდებარეობს _mongodb._tcp.<hostname>-ზე და თითო წევრზე ერთ სამიზნე ჰოსტის სახელს და პორტს შეიცავს. TXT ჩანაწერი თავად ჰოსტის სახელზეა და შეიცავს URI-ის პარამეტრებს query-string სახით, მაგალითად authSource=admin&replicaSet=rs0. იქ მხოლოდ სამი პარამეტრია დაშვებული - authSource, replicaSet და loadBalanced - და TXT ჩანაწერი მხოლოდ ერთი შეიძლება იყოს; ერთზე მეტი შეცდომაა. URI-ში პირდაპირ დაწერილი ყველაფერი TXT ჩანაწერს გადაფარავს.
ზუსტად იმის ნახვა, რასაც დრაივერი ნახავს, ჩვეულებრივი DNS ხელსაწყოებითაც შეიძლება:
$ dig +short SRV _mongodb._tcp.cluster0.example.net0 0 27017 shard-00-00.example.net.0 0 27017 shard-00-01.example.net.0 0 27017 shard-00-02.example.net.$ dig +short TXT cluster0.example.net"authSource=admin&replicaSet=rs0"Windows-ზე იგივეს აკეთებს nslookup -type=SRV _mongodb._tcp.cluster0.example.net. თუ SRV მოთხოვნა ცარიელს დააბრუნებს, აპლიკაციაში შეცდომა იქნება querySrv ENOTFOUND (Node) ან ConfigurationError DNS სახელის ხსენებით (PyMongo), და პარამეტრების არც ერთი ცვლილება არ დაგეხმარება.
დიზაინიდან გამომდინარე წესები:
- ზუსტად ერთი ჰოსტის სახელი და არანაირი პორტი. პორტები SRV ჩანაწერებიდან მოდის.
- SRV ჩანაწერის დაბრუნებული ჰოსტის სახელები იმავე მშობელ დომენში უნდა იყოს, რომელშიც მოთხოვნილი სახელია.
cluster0.example.netშეიძლებაshard-00-00.example.net-ზე მიუთითებდეს, მაგრამ არაdb.othercompany.com-ზე; დრაივერები უსაფრთხოების მიზნით ასეთ სამიზნეებს უარყოფენ. ძველი დრაივერები სახელში წერტილებით გამოყოფილ სულ მცირე სამ ნაწილსაც მოითხოვდნენ, რაც უფრო ახალ ვერსიებში შემსუბუქდა - თუ ორნაწილიანი სახელი არ მუშაობს, შეამოწმე შენი დრაივერის changelog. - TLS ნაგულისხმევად ჩართულია. თუ ნამდვილად დაუშიფრავი კავშირი გინდა,
tls=falseპირდაპირ დაამატე, რაც+srv-თან თითქმის არასდროს გჭირდება. directConnection=true+srv-თან დაუშვებელია, რადგან მთელი აზრი სწორედ ისაა, რომ დრაივერმა რამდენიმე სერვერი აღმოაჩინოს.- ორი ახალი პარამეტრი ამ მოთხოვნას არეგულირებს:
srvServiceName(ნაგულისხმევიmongodb) ცვლის ჩანაწერის სახელის_mongodbნაწილს, ხოლოsrvMaxHostsზღუდავს, დაბრუნებული ჰოსტებიდან რამდენი გამოიყენოს; ესmongosროუტერების დიდი ჯგუფებისთვისაა განკუთვნილი.
mongos-ის გავლით დაკავშირებულ sharded კლასტერებზე დრაივერები SRV ჩანაწერს პერიოდულად ხელახლა ეკითხებიან და ჩანაწერების ცვლილებასთან ერთად როუტერებს ამატებენ ან აკლებენ. replica set-ისთვის ეს საჭირო არ არის, რადგან პირველი კავშირის დამყარების შემდეგ თავად set იტყობინება თავის შემადგენლობას.
mongodb+srv:// ღირს მაშინ, როცა ამ ჩანაწერებს ვიღაც შენ მაგივრად ინახავს - მართული კლასტერი, რომლის წევრებიც იცვლება, ან შენი საკუთარი replica set, რომლის ჩანაწერებსაც საკუთარ DNS ზონაში აქვეყნებ. ერთი სერვერისთვის ის არ ღირს. ერთი ბაზა A ჩანაწერით და mongodb://db.example.net:27017 უფრო მარტივია, დამატებით მოთხოვნებს არ საჭიროებს და ნაკლები საინტერესო გზით ტყდება. DNS ჩანაწერების განმარტება ფარავს A, TXT და SRV ტიპებს, თუ მათ თავად გამოქვეყნებას აპირებ.
რამდენიმე ჰოსტი და replicaSet#
მძიმეებით გამოყოფილი ჰოსტების სია საწყისი სიაა. დრაივერი უკავშირდება მიცემულ ჰოსტებს, თითოეულს ეკითხება, როგორ ხედავს replica set საკუთარ თავს (hello ბრძანება) და ამის შემდეგ URI-ზე კი არა, სერვერის პასუხზე დაყრდნობით მუშაობს.
mongodb://db1.example.net:27017,db2.example.net:27017,db3.example.net:27017/shop?replicaSet=rs0პრაქტიკაში ეს ნიშნავს:
- ყველა წევრის ჩამოთვლა საჭირო არ არის. აღმოსაჩენად ერთი ხელმისაწვდომი წევრიც საკმარისია, თუმცა ყველას ჩამოთვლა იმას უზრუნველყოფს, რომ გაშვება მაშინაც იმუშავებს, როცა პირველი ჩამოვარდნილია.
- ჰოსტების თანმიმდევრობა არ განსაზღვრავს, სად მიდის ჩაწერა. ჩაწერა ყოველთვის მიმდინარე primary-ზე მიდის; წაკითხვა იქ მიდის, საითაც
readPreferenceმიმართავს. replicaSetset-ის რეალურ სახელს უნდა ემთხვეოდეს (rs.initiate()-ზე მიცემული_id). წევრი, რომელიც სხვა set-ის სახელს აცხადებს, ტოპოლოგიიდან ამოღებულია, და თუ ყველა წევრი ამოიღეს, გამართულ შეტყობინებას კი არა, server selection timeout-ს მიიღებ.mongosh-შიdb.hello().setNameრეალურ სახელს გიჩვენებს.- ჰოსტების სახელები, რომლებსაც დრაივერი საბოლოოდ იყენებს, replica set-ის კონფიგურაციიდანაა და არა შენი URI-დან. თუ set
localhost:27017-ით ან Docker-ის შიდა კონტეინერების სახელებით ინიცირდა, ამ ქსელის გარეთ მყოფი კლიენტი აღმოაჩენს ჰოსტის სახელებს, რომელთა გარჩევა არ შეუძლია, და წარმატებული პირველი კონტაქტის შემდეგ timeout-ს იღებს. წევრების ჰოსტის სახელებიrs.reconfig()-ით replica set-ის კონფიგურაციაში გაასწორე; კლიენტის მხარეს ამას ნუ შეამალავ.
sharded კლასტერისთვის ჰოსტების სია mongos როუტერებს ასახელებს, replicaSet პარამეტრი არ არსებობს და დრაივერი ოპერაციებს ხელმისაწვდომ როუტერებზე ანაწილებს, უპირატესობას უმცირესი დაყოვნების მქონეებს ანიჭებს.
directConnection
directConnection=true დრაივერს ეუბნება, რომ მხოლოდ URI-ში მითითებულ ერთ ჰოსტთან ისაუბროს და აღმოჩენა გამოტოვოს. ის მხოლოდ ერთ ჰოსტთან არის დაშვებული და +srv-თან არასდროს. გამოიყენე, როცა:
- გინდა კონკრეტულ წევრს დაუკავშირდე, ჩვეულებრივ secondary-ს, მოვლისთვის ან primary-ს შეხების გარეშე მოთხოვნის გასაშვებად.
- replica set-ის კონფიგურირებული ჰოსტის სახელები იქიდან მიუწვდომელია, სადაც შენ ხარ, მაგალითად ერთ წევრამდე SSH tunnel-ით. ამ მოწყობას აღწერს SSH tunnels და port forwarding.
ნაგულისხმევს მნიშვნელობა აქვს და ის შეიცვალა. PyMongo 4-სა და Node-ის დრაივერში 4.0-დან directConnection ნაგულისხმევად false-ია, ამიტომ URI, რომელშიც ერთი ჰოსტია და ის replica set-ის წევრია, აღმოჩენას იღებს: დრაივერი primary-ს პოულობს და ჩაწერას იქ აგზავნის. PyMongo 3 ერთი ჰოსტის შემთხვევაში იქცეოდა ისე, თითქოს true იყო. კოდი, რომელიც განახლების შემდეგ „მხოლოდ იმ მანქანასთან დაკავშირებაზე“ იყო დამოკიდებული, უცებ სხვა სერვერს ელაპარაკება, ამიტომ როცა განსხვავებას მნიშვნელობა აქვს, პარამეტრი პირდაპირ მიუთითე. standalone სერვერზე, რომელიც replica set-ს საერთოდ არ აცხადებს, ორივე მნიშვნელობა ერთსა და იმავე შედეგამდე მიდის.
loadBalanced=true მესამე ტოპოლოგიური პარამეტრია, კლასტერებისთვის, რომლებიც MongoDB პროტოკოლის მცოდნე load balancer-ის უკანაა (იყენებენ ზოგიერთი მართული serverless შეთავაზება). მისი გაერთიანება replicaSet-თან, directConnection=true-თან ან ერთზე მეტ ჰოსტთან არ შეიძლება და მას მხოლოდ პროვაიდერის მოცემულ URI-ში შეხვდები.
პარამეტრები, რომლებიც ქცევას ცვლის#
URI პარამეტრების სრული სია გრძელია. ეს ის პარამეტრებია, რომლებიც რეალურ connection string-ებში ჩანს და კლიენტის ქცევას ცვლის.
| Option | Default | Effect |
|---|---|---|
authSource | path db, else admin | მომხმარებლის შემცველი ბაზა |
tls | false; true for +srv | აშიფრავს კავშირს |
retryWrites | true | ჩავარდნილ ჩაწერას ერთხელ იმეორებს |
w | server default | ჩაწერის დადასტურება |
readPreference | primary | რომელი წევრები ემსახურებიან წაკითხვას |
maxPoolSize | 100 | კავშირები თითო სერვერზე |
connectTimeoutMS | driver-specific | TCP კავშირის timeout |
appName | none | წარწერა სერვერის ლოგებში |
directConnection | false | გამოტოვებს ტოპოლოგიის აღმოჩენას |
authSource
ასახელებს ბაზას, სადაც მომხმარებელი შეიქმნა. ნაგულისხმევის წესები ზემოთაა, პრობლემების გადაჭრა კი ავთენტიფიკაციის გზამკვლევში. აქ დასამატებელი მხოლოდ ბრძანების ხაზის ეკვივალენტია: mongosh იღებს --authenticationDatabase-ს, რომელიც იგივე პარამეტრია სხვა სახელით.
tls
tls=true აშიფრავს კავშირს და სერვერის სერტიფიკატს ამოწმებს სისტემის სანდო საცავის მიხედვით, ან tlsCAFile-ში დასახელებული CA-ით. ssl=true უფრო ძველი სინონიმია და ისევ მუშაობს. სერვერი ჯერ TLS-ისთვის უნდა იყოს გამართული; URI-ში მისი ჩართვა სერვერზე, რომელზეც ეს არ არის გაკეთებული, handshake-ზე ჩავარდება და ჩვეულებრივ timeout-ად ჩანს. tlsAllowInvalidCertificates=true და tlsInsecure=true ტესტირებისთვისაა და პროდაქშენში არასდროს უნდა მოხვდეს.
retryWrites და w
retryWrites=true დრაივერებში ნაგულისხმევია MongoDB 4.2-ის ეპოქიდან. ჩაწერა, რომელიც ქსელის შეცდომით ან primary-ს არჩევნებით ჩავარდა, ერთხელ და უსაფრთხოდ მეორდება, რადგან სერვერი ოპერაციის იდენტობას აკონტროლებს. განმეორებადი ჩაწერებისთვის replica set ან sharded კლასტერი სჭირდება; standalone სერვერზე დრაივერი უბრალოდ არ იმეორებს. ხანდახან შეგხვდება retryWrites=false ძველი სერვერებისთვის ან უჩვეულო storage engine-ებისთვის დაწერილ სტრიქონებში - დატოვე ნაგულისხმევზე, სანამ სერვერის შეცდომა სხვას არ გეტყვის.
w write concern-ს აყენებს: w=1 ნიშნავს, რომ primary-მ ჩაწერა დაადასტურა, w=majority - რომ ხმის უფლების მქონე წევრების უმრავლესობამ, ხოლო w=0 - რომ არავინ დაადასტურა და წარუმატებლობის შესახებ არასდროს გაიგებ. MongoDB 5.0-დან სერვერის იმპლიციტური ნაგულისხმევი უმეტეს replica set-ზე majority-ა, ამიტომ w-ს URI-დან გამოტოვება ჩვეულებრივ სწორია. journal=true ამატებს პირობას „და ის დისკზეა ჟურნალში“, ხოლო wtimeoutMS majority ჩაწერას უკრძალავს უსასრულოდ ლოდინს, როცა ძალიან ცოტა წევრია ჩართული. ერთ სერვერზე majority მხოლოდ იმ სერვერით კმაყოფილდება.
readPreference
იღებს primary, primaryPreferred, secondary, secondaryPreferred და nearest მნიშვნელობებს. primary-ის გარდა ყველაფერმა შეიძლება ოდნავ ჩამორჩენილი მონაცემები დააბრუნოს, რადგან secondary-ები ასინქრონულად იმეორებენ. maxStalenessSeconds (მინიმუმ 90) გამორიცხავს secondary-ებს, რომლებიც ძალიან ჩამორჩნენ, ხოლო readPreferenceTags=dc:east წაკითხვას შესაბამისი ტეგების მქონე წევრებისკენ მიმართავს. ერთი ჰოსტის შემთხვევაში არჩევანი არ არსებობს.
maxPoolSize და connectTimeoutMS
maxPoolSize ეხება თითო სერვერს, თითო კლიენტზე. ერთ კლიენტს, რომელიც სამწევრიან replica set-თან მუშაობს, ნაგულისხმევით სამასამდე კავშირის გახსნა შეუძლია, და შენი აპლიკაციის ყოველ პროცესს საკუთარი კლიენტი აქვს. დააყენე შეგნებულად; connection pools და ლიმიტები შეიცავს არითმეტიკას. minPoolSize კავშირებს თბილად ინახავს, maxIdleTimeMS კი უსაქმოებს ხურავს.
connectTimeoutMS თითოეული კავშირის TCP timeout-ია და მისი ნაგულისხმევი იმ ცოტა მნიშვნელობათაგანია, რომლებიც დრაივერებს შორის განსხვავდება: საერთო სპეციფიკაცია 10 წამს ამბობს, PyMongo 20-ს იყენებს, Node-ის დრაივერი - 30-ს. ის ის პარამეტრი არ არის, რაც არასწორ URI-ს ჩამოკიდებას იწვევს - ეს serverSelectionTimeoutMS-ია, ყველგან 30 წამი. ახალი დრაივერები timeoutMS-ს ასევე მხარს უჭერენ: ერთი კლიენტის მხარეს ლიმიტი მთელ ოპერაციაზე, რომელიც რამდენიმე უფრო ძველი ეტაპობრივი timeout-ის ჩანაცვლებას ისახავს მიზნად.
appName
თავისუფალი ტექსტის წარწერა, 128 ბაიტამდე, რომელიც კავშირის handshake-ში იგზავნება. ის ჩანს სერვერის ლოგში ყოველი კავშირისთვის და db.currentOp()-ში, ამიტომ ხედავ, რომელმა სერვისმა რომელი კავშირები გახსნა. არაფერი უჯდება; დააყენე ყველა კლიენტზე.
URI-ების აგება გავრცელებული სცენარებისთვის#
უმეტესი სტრიქონი რამდენიმე ფორმას ექვემდებარება. მათი გვერდიგვერდ წაკითხვა სპეციფიკაციის კითხვაზე სწრაფია.
# Local developmentmongodb://127.0.0.1:27017/shop# One remote server, user in adminmongodb://shopapp:pw@db.example.net:27017/shop?authSource=admin&appName=api# Three-member replica set, reads to secondaries allowedmongodb://shopapp:pw@db1.example.net,db2.example.net,db3.example.net/shop ?replicaSet=rs0&authSource=admin&readPreference=secondaryPreferred# One member only, through an SSH tunnel on local port 27018mongodb://shopapp:pw@127.0.0.1:27018/shop?directConnection=true&authSource=admin# Managed cluster published in DNSmongodb+srv://shopapp:pw@cluster0.example.net/shop?appName=api# Same cluster written out by hand (what +srv was doing for you)mongodb://shopapp:pw@shard-00-00.example.net:27017,shard-00-01.example.net:27017 ,shard-00-02.example.net:27017/shop?replicaSet=rs0&authSource=admin&tls=truereplica set-ის მაგალითებში ხაზის გადატანები მხოლოდ კითხვის სიმარტივისთვისაა; რეალური URI ერთი ხაზია, ინტერვალების გარეშე. ბოლო მაგალითი ის არის, რომელიც უნდა დაიმახსოვრო, როცა პრობლემა DNS-შია: +srv-ის უბრალო სიად გადაქცევა ნიშნავს ჰოსტების გადაწერას SRV ჩანაწერიდან, პარამეტრების TXT ჩანაწერიდან და tls=true-ს თავად დამატებას. სამიდან ერთიც რომ გამოტოვო, კავშირი სხვადასხვანაირად ჩავარდება.
სად იწერება სტრიქონი თითოეულ კლიენტში#
ყველა ოფიციალური დრაივერი ერთსა და იმავე URI-ს იღებს, რაც ერთიანი ფორმატის მთელი აზრია. განსხვავდება ის, საიდან იკითხება სტრიქონი და რა რას გადაფარავს.
PyMongo
import osfrom pymongo import MongoClientclient = MongoClient(os.environ["MONGODB_URI"], appName="reports", maxPoolSize=10)db = client.get_default_database() # the /database from the URIkeyword არგუმენტები და URI პარამეტრები ურთიერთშემცვლელია, და როცა ერთი და იგივე პარამეტრი ორივეგანაა, keyword არგუმენტი იმარჯვებს. get_default_database() აბრუნებს გზაში დასახელებულ ბაზას და შეცდომას იძლევა, თუ გზა არ არის. სტრიქონის დაკავშირების გარეშე შესამოწმებლად pymongo.uri_parser.parse_uri(uri) აბრუნებს გაშიფრულ ჰოსტებს, მონაცემებს და პარამეტრებს ლექსიკონის სახით და ნებისმიერ არასწორ რამეზე შეცდომას იძლევა, მათ შორის +srv სახელზე, რომელსაც ჩანაწერები არ აქვს.
Node.js-ის დრაივერი
import { MongoClient } from "mongodb";const client = new MongoClient(process.env.MONGODB_URI, { appName: "api" });const db = client.db(); // the /database from the URIმეორე არგუმენტი იგივე პარამეტრებს camelCase-ში იღებს. client.db() სახელის გარეშე URI-ის ნაგულისხმევ ბაზას აბრუნებს. Mongoose სტრიქონს უცვლელად გადასცემს mongoose.connect(uri)-ით. გაშიფვრას აკეთებს mongodb-connection-string-url პაკეტი, რომელზეც დრაივერია დამოკიდებული და რომლის გამოყენებაც თავადაც შეგიძლია URI-ის შესამოწმებლად ან პაროლის დასამალად ლოგში ჩაწერამდე.
mongosh
$ mongosh 'mongodb://db1.example.net,db2.example.net/shop?replicaSet=rs0' \ -u shopapp -p --authenticationDatabase adminURI ერთ ბრჭყალებში ჩასვი, რომ shell-მა & და $ არ შეეხოს. mongosh replica set-ს უფრო ძველი ფორმითაც იღებს: --host rs0/db1.example.net:27017,db2.example.net:27017. დაკავშირების შემდეგ db.hello() აჩვენებს setName-ს, წევრების სიას და იმას, რომელია primary, რაც ნებისმიერ ეჭვს ფანტავს იმის შესახებ, რას აღმოაჩენს დრაივერი.
.NET: appsettings.json და web.config
C#-ის დრაივერი URI-ს სტრიქონად იღებს, ASP.NET Core-ში კი ის ConnectionStrings სექციაშია:
{ "ConnectionStrings": { "Mongo": "mongodb://shopapp:pw@db.example.net:27017/shop?authSource=admin" }}var cs = builder.Configuration.GetConnectionString("Mongo");var url = new MongoUrl(cs);builder.Services.AddSingleton<IMongoClient>(new MongoClient(url));builder.Services.AddSingleton(sp => sp.GetRequiredService<IMongoClient>().GetDatabase(url.DatabaseName));MongoUrl სტრიქონს შლის და მისი DatabaseName გზის ბაზას გაძლევს. კლიენტი singleton-ად დაარეგისტრირე იმავე მიზეზით, რაც ყველა სხვა დრაივერზეა: ის pool-ია. პროდაქშენში მნიშვნელობა გარემოს ცვლადად ConnectionStrings__Mongo დააყენე და პაროლი ფაილში ნუ ჩაწერ; ეს მიდგომა აღწერილია აქ: გარემოს ცვლადები და საიდუმლოებები.
.NET Framework-ზე სტრიქონი web.config-ში ან app.config-შია და იკითხება ConfigurationManager.ConnectionStrings["Mongo"].ConnectionString-ით. ეს ფაილი XML-ია, ამიტომ პარამეტრებს შორის ყოველი & &-ად უნდა დაიწეროს:
<connectionStrings> <add name="Mongo" connectionString="mongodb://db.example.net:27017/shop?authSource=admin&appName=legacy" /></connectionStrings>იქ ჩვეულებრივი & მთელ კონფიგურაციის ფაილს ჩატვირთვაზე ჩააგდებს, რაც ხშირად აპლიკაციის გაშვების შეცდომად ჩანს, MongoDB-ის ხსენების გარეშე. იგივე იდეა SQL Server-ის სტრიქონებისთვის აღწერილია აქ: SQL Server connection strings.
Compass
URI ჩასვი ახალი კავშირის ეკრანის ველში. „Advanced Connection Options“ მას ჩანართებად ყოფს: General ჩანართზე არის გადამრთველი mongodb-სა და mongodb+srv-ს შორის, ჰოსტების სია და Direct Connection-ის ჩექბოქსი; Authentication შეიცავს მომხმარებლის სახელს, პაროლს და ავთენტიფიკაციის ბაზას; TLS/SSL და Proxy/SSH თავიანთ ჩანართებზეა. ჩანართებში ცვლილებები სტრიქონს ხელახლა წერს და პირიქით, რის გამოც Compass კარგი გზაა იმის სანახავად, როგორ იშიფრება შენთვის გამოგზავნილი URI - იმის ჩათვლით, ჰოსტების სია ისე გაიშიფრა თუ არა, როგორც გულისხმობდი.
შეცდომები, რომლებიც თავად ფორმატს ეხება#
ეს შეცდომები სტრიქონის ფორმით არის გამოწვეული და არა მონაცემებით ან ქსელით.
- პორტი `+srv` URI-ზე.
mongodb+srv://cluster0.example.net:27017პირდაპირ უარყოფილია. პორტი ამოშალე. - რამდენიმე ჰოსტი `+srv` URI-ზე. ესეც უარყოფილია;
+srvერთ სახელს იღებს. - `directConnection=true` რამდენიმე ჰოსტთან. უარყოფილია, რადგან პირდაპირ დასაკავშირებელი ერთი სერვერი არ არის.
- `replicaSet`-ის სახელი, რომელიც არ ემთხვევა. server selection 30 წამის შემდეგ timeout-ით სრულდება, მაშინ როცა ყველა ჰოსტი ხელმისაწვდომი იყო. შეადარე
db.hello().setName-ს. - „სარეზერვოს“ აზროვნება. ერთ URI-ში პროდაქშენ სერვერისა და სარეზერვო სერვერის ჩამოთვლა დაუკავშირებელ მანქანებს შორის failover-ს არ ქმნის. თუ ისინი ერთი replica set-ის წევრები არ არიან, დრაივერი ორ ტოპოლოგიას ხედავს, რომლებიც ერთმანეთს ეწინააღმდეგება, და რეზერვის ნაცვლად შეცდომებს იღებ.
- ინტერვალები ან ხაზის გადატანები. დოკუმენტიდან ან მესიჯიდან გადატანილი URI-ს კოპირებისას მას ინტერვალი ან ახალი ხაზი მოჰყვება. დრაივერები არასწორ ჰოსტს ან უცნობ პარამეტრს აცხადებენ, ზედმეტი სიმბოლო კი ლოგების უმეტესობაში უხილავია.
- დაუკოდირებელი სპეციალური სიმბოლოები პაროლში. დეტალურად განხილულია აქ: MongoDB connection strings; მოკლედ - დაშიფრე ერთხელ, ან მონაცემები ცალკე პარამეტრებად გადაეცი.
RE:NODE-ის MongoDB ჰოსტინგზე თითოეული სერვერი იქმნება მისთვის გენერირებული მონაცემებით და მასთან პირდაპირ უკავშირდებიან პლანზე ნაჩვენები ჰოსტითა და პორტით. მისთვის SRV ჩანაწერები არ ქვეყნდება და წინ proxy არ დგას, ამიტომ სწორი ფორმაა mongodb:// ამ ჰოსტითა და პორტით, გენერირებული მომხმარებლით და authSource-ით, რომელიც იმ ბაზაზე მიუთითებს, სადაც მომხმარებელი ცხოვრობს. გზამკვლევების მონაცემთა ბაზების განყოფილება გიჩვენებს, სად ჩამოთვლის პანელი ამ დეტალებს. თუ შენი აპლიკაცია app line-ებიდან რომელიმეზე მუშაობს, მაგალითად Python, Node.js ან C# / .NET, URI იმ სერვერის გარემოს ცვლადებში იწერება Startup ჩანართზე და არა კოდში.
FAQ#
რა არის MongoDB-ის ნაგულისხმევი URI?
mongodb://localhost:27017, მონაცემებისა და ბაზის გარეშე. თუ შენს მანქანაზე localhost IPv6-ზე იშლება, mongod კი მხოლოდ IPv4-ზე უსმენს, გამოიყენე mongodb://127.0.0.1:27017.
შეიძლება თუ არა mongodb+srv IP მისამართთან გამოყენება?
არა. +srv არსებობს DNS სახელის SRV და TXT ჩანაწერების მოსაძებნად, IP მისამართს კი ისინი არ აქვს. გამოიყენე mongodb:// მისამართითა და პორტით.
საჭიროა თუ არა URI-ში replica set-ის ყველა წევრის ჩამოთვლა?
არა. ერთი ხელმისაწვდომი წევრი საკმარისია, რადგან დანარჩენს დრაივერი set-ისგან სწავლობს. ორის ან სამის ჩამოთვლა ნიშნავს, რომ კლიენტი მაშინაც ჩაირთვება, როცა ერთი მათგანი ჩამოვარდნილია, და სწორედ ამიტომ ჩამოთვლის უმეტესი პროდაქშენ სტრიქონი.
რატომ დაიწყო ჩემმა აპლიკაციამ სხვა სერვერზე ჩაწერა დრაივერის განახლების შემდეგ?
სავარაუდოდ directConnection-ის ნაგულისხმევი შეიცვალა. ახალი დრაივერები replica set-ს ერთი ჰოსტიდან აღმოაჩენენ და ჩაწერას primary-ზე გადაამისამართებენ. დაამატე directConnection=true, თუ ნამდვილად იმ ერთ სერვერს გულისხმობ, და გამოტოვე, თუ replica set-ის ჩვეულებრივი ქცევა გინდა.
აქვს თუ არა URI-ში პარამეტრების რიგს მნიშვნელობა?
არა. პარამეტრები გასაღები-მნიშვნელობის წყვილების ერთობლიობაა. მნიშვნელობა აქვს იმას, რომ URI-ში მითითებული პარამეტრი +srv-ის TXT ჩანაწერის იმავე პარამეტრს გადაფარავს, ხოლო კოდში გადაცემული დრაივერის არგუმენტები URI-ს ჩვეულებრივ გადაფარავს.
რას აკეთებს replicaSet ერთ სერვერზე?
standalone სერვერზე ის კავშირს აჩავარდებს, რადგან სერვერი set-ის სახელს არ აცხადებს, დრაივერი კი rs0-ის წევრს ელოდება. replicaSet მხოლოდ მაშინ დაამატე, როცა სერვერი ნამდვილად replica set-ის წევრია, ერთწევრიანი set-ისაც კი.


