隨筆 - 22, 文章 - 0, 評論 - 1, 引用 - 0
          數(shù)據(jù)加載中……

          mongoDB java驅(qū)動(dòng)學(xué)習(xí)筆記

          指定新mongo實(shí)例:
          Mongo m = new Mongo();
          Mongo m = new Mongo( "localhost" );
          Mongo m = new Mongo( "localhost" , 27017 );
          // or, to connect to a replica set, supply a seed list of members
          Mongo m = new Mongo(Arrays.asList(new ServerAddress("localhost", 27017),
                                                new ServerAddress("localhost", 27018),
                                                new ServerAddress("localhost", 27019)));
          然后發(fā)起連接(必須指定數(shù)據(jù)庫名,可以不存在)
          DB db = m.getDB( "mydb" );
          注意Mongo已經(jīng)實(shí)現(xiàn)了連接池,并且是線程安全的。
          大部分用戶使用mongodb都在安全內(nèi)網(wǎng)下,但如果將mongodb設(shè)為安全驗(yàn)證模式,就需要在客戶端提供用戶名和密碼:
          boolean auth = db.authenticate(myUserName, myPassword);
          獲取集合(collection)的名稱列表(類似show databases):
          Set<String> colls = db.getCollectionNames();
          獲取一個(gè)集合(以便增刪改查操作):
          DBCollection coll = db.getCollection("testCollection")
          -------------------------------------------------------------
          先假設(shè)要插入的json數(shù)據(jù)如下:
          {
             "name" : "MongoDB",
             "type" : "database",
             "count" : 1,
             "info" : {
                         x : 203,
                         y : 102
                       }
          }
          將其插入數(shù)據(jù)庫:
                  BasicDBObject doc = new BasicDBObject();
                  doc.put("name", "MongoDB");
                  doc.put("type", "database");
                  doc.put("count", 1);
                  BasicDBObject info = new BasicDBObject();
                  info.put("x", 203);
                  info.put("y", 102);
                  doc.put("info", info);
                  coll.insert(doc);
          -------------------------------------------------------------
          設(shè)定write concern,以便操作失敗時(shí)得到提示:
          m.setWriteConcern(WriteConcern.SAFE);
          -------------------------------------------------------------
          查找一個(gè)/第一個(gè)記錄:
          DBObject myDoc = coll.findOne();
          System.out.println(myDoc);
          注意:屬性名不能以下劃線或者美元符號開始,mongodb自己保留。
          獲取總記錄數(shù):
          System.out.println(coll.getCount());
          使用游標(biāo)操作查詢結(jié)果:
                  DBCursor cursor = coll.find();
                  try {
                      while(cursor.hasNext()) {
                          System.out.println(cursor.next());
                      }
                  } finally {
                      cursor.close();
                  }
          條件查詢:
                  BasicDBObject query = new BasicDBObject();
                  query.put("i", 71);
                  cursor = coll.find(query);
                  try {
                      while(cursor.hasNext()) {
                          System.out.println(cursor.next());
                      }
                  } finally {
                      cursor.close();
                  }
          如果想使用shell里的類似以下語句的功能:
          db.things.find({j: {$ne: 3}, k: {$gt: 10} });
          在java驅(qū)動(dòng)里,{$ne: 3}也是一個(gè)普通的DBObject:
                  BasicDBObject query = new BasicDBObject();
                  query.put("j", new BasicDBObject("$ne", 3));
                  query.put("k", new BasicDBObject("$gt", 10));
                  cursor = coll.find(query);
                  try {
                      while(cursor.hasNext()) {
                          System.out.println(cursor.next());
                      }
                  } finally {
                      cursor.close();
                  }
          條件查詢一批數(shù)據(jù):
          以下是查詢i > 50的記錄:
                  query = new BasicDBObject();
                  query.put("i", new BasicDBObject("$gt", 50));  // e.g. find all where i > 50
                  cursor = coll.find(query);
                  try {
                      while(cursor.hasNext()) {
                          System.out.println(cursor.next());
                      }
                  } finally {
                      cursor.close();
                  }         
          以下是查詢20 < i <= 30的記錄:
                  query = new BasicDBObject();
                  query.put("i", new BasicDBObject("$gt", 20).append("$lte", 30));  // i.e.   20 < i <= 30
                  cursor = coll.find(query);
                  try {
                      while(cursor.hasNext()) {
                          System.out.println(cursor.next());
                      }
                  } finally {
                      cursor.close();
                  }
          -------------------------------------------------------------
          創(chuàng)建索引:
          指定collection和要index的列即可,1代表升序,-1代表降序。
          coll.createIndex(new BasicDBObject("i", 1));  // create index on "i", ascending
          獲取索引列表:
          List<DBObject> list = coll.getIndexInfo();
                    for (DBObject o : list) {
                      System.out.println(o);
                  }
          -------------------------------------------------------------
          數(shù)據(jù)庫管理相關(guān)的命令:
          獲取數(shù)據(jù)庫名稱列表:
          m.getDatabaseNames()
          刪除數(shù)據(jù)庫:
          m.dropDatabase("my_new_db");
          -------------------------------------------------------------
          聚合函數(shù):使用DBCollection.aggregate()產(chǎn)生聚合任務(wù):
          http://www.mongodb.org/display/DOCS/Using+The+Aggregation+Framework+with+The+Java+Driver
          // create our pipeline operations, first with the $match
          DBObject match = new BasicDBObject("$match", new BasicDBObject("type", "airfare") );
          // build the $projection operation
          DBObject fields = new BasicDBObject("department", 1);
          fields.put("amount", 1);
          fields.put("_id", 0);
          DBObject project = new BasicDBObject("$project", fields );
          // Now the $group operation
          DBObject groupFields = new BasicDBObject( "_id", "$department");
          groupFields.put("average", new BasicDBObject( "$avg", "$amount"));
          DBObject group = new BasicDBObject("$group", groupFields);
          // run aggregation
          AggregationOutput output = collection.aggregate( match, project, group );
          返回結(jié)果是一個(gè)AggregationOutput對象,可以用以下方式獲取其中信息:
          public Iterable<DBObject> results()
          public CommandResult getCommandResult
          public DBObject getCommand()
          示例:
          System.out.println(output.getCommandResult());
          {
          "serverUsed" : "/127.0.0.1:27017" ,
          "result" : [
          {"_id" : "Human Resources" , "average" : 74.91735537190083} ,
          {"_id" : "Sales" , "average" : 72.30275229357798} ,
          {"_id" : "Engineering" , "average" : 74.1}
          ] ,
          "ok" : 1.0
          }
          -------------------------------------------------------------
          使用DBObject存取對象:
          http://www.mongodb.org/display/DOCS/Java+-+Saving+Objects+Using+DBObject
          假設(shè)一個(gè)類叫做twitter,存儲前必須實(shí)現(xiàn)DBObject接口:
          public class Tweet implements DBObject {
              /* ... */
          }
          然后就可以存了:
          Tweet myTweet = new Tweet();
          myTweet.put("user", userId);
          myTweet.put("message", msg);
          myTweet.put("date", new Date());
          collection.insert(myTweet);
          一個(gè)文檔從數(shù)據(jù)庫取出時(shí),自動(dòng)被轉(zhuǎn)為DBObject。如果想取出時(shí)轉(zhuǎn)為需要的類,可以先調(diào)用DBCollection.setObjectClass(),然后再進(jìn)行類型強(qiáng)制轉(zhuǎn)換:
          collection.setObjectClass(Tweet.class);
          Tweet myTweet = (Tweet)collection.findOne();
          如果想要改變Tweet類的屬性,可以改完后再存入:
          Tweet myTweet = (Tweet)collection.findOne();
          myTweet.put("message", newMsg);
          collection.save(myTweet);
          -------------------------------------------------------------
          JAVA驅(qū)動(dòng)的并發(fā):
          http://www.mongodb.org/display/DOCS/Java+Driver+Concurrency
          mongodb的java驅(qū)動(dòng)是線程安全的,如果是在web服務(wù)環(huán)境下,應(yīng)該創(chuàng)建單例的mongo對象,用這個(gè)對象處理每一個(gè)請求。mongo對象維護(hù)一個(gè)內(nèi)部連接池(默認(rèn)大小為10),對于每個(gè)請求(查找插入等),java線程會(huì)從線程池取一個(gè)連接,執(zhí)行操作,然后釋放連接——這意味著每次操作所使用的連接很有可能是不同的。
          ------------------------------
          在復(fù)制(replica)模式下,如果設(shè)置slaveOK選項(xiàng)為on,那么讀操作會(huì)被均勻的分布到各個(gè)slave上。這意味著對于同一個(gè)線程,一個(gè)寫操作后緊跟著的一個(gè)讀操作,有可能被發(fā)送到不同的服務(wù)器上(寫操作發(fā)送到master上,讀操作發(fā)送到slave上),這樣讀操作有可能不會(huì)立刻反映出上一個(gè)寫操作的數(shù)據(jù)(因?yàn)橹鲝牡漠惒叫?。
          如果你想要確保在一個(gè)session中完整的一致性(例如在一個(gè)http請求中),你可能希望java驅(qū)動(dòng)是用同一個(gè)socket連接,這時(shí)你可以通過使用"consistent request"來達(dá)到目的——在操作前后分別調(diào)用requestStart()和requestDone()。
          DB db...;
          db.requestStart();
          try {
             //Ensures that a connection exists for the "consistent request"
             db.requestEnsureConnection();
             code....
          } finally {
             db.requestDone();
          }
          ------------------------------
          在單獨(dú)寫操作上的WriteConcern選項(xiàng):
          默認(rèn)情況下,每次寫操作后,連接就被釋放回連接池——此時(shí)你調(diào)用getLastError()是沒用的。
          所以可以采用兩種方式:
          1,使用類似WriteConcern.SAFE這樣的寫策略來代替默認(rèn)策略,這樣java驅(qū)動(dòng)會(huì)自動(dòng)首先調(diào)用getLastError(),然后才將連接放回連接池。
          DBCollection coll...;
          coll.insert(..., WriteConcern.SAFE);
          2,采用上述的requestStart()和requestDone()方式來維持連接不被釋放,中間調(diào)用getLastError()獲取錯(cuò)誤信息。
          DB db...;
          DBCollection coll...;
          db.requestStart();
          try {
             coll.insert(...);
             DBObject err = db.getLastError();
          } finally {
             db.requestDone();
          }
          這兩種方式等價(jià)。
          -------------------------------------------------------------
          java類型:
          http://www.mongodb.org/display/DOCS/Java+Types
          ----------------------------
          Object id被用來自動(dòng)生成唯一的ID:
          ObjectId id = new ObjectId();
          ObjectId copy = new ObjectId(id);
          ----------------------------
          正則表達(dá)式:
          java驅(qū)動(dòng)使用JDK的java.util.regex.Pattern表達(dá)正則:
          Pattern john = Pattern.compile("joh?n", CASE_INSENSITIVE);
          BasicDBObject query = new BasicDBObject("name", john);
          // finds all people with "name" matching /joh?n/i
          DBCursor cursor = collection.find(query);
          ----------------------------
          java驅(qū)動(dòng)使用JDK的 java.util.Date表示日期時(shí)間:
          Date now = new Date();
          BasicDBObject time = new BasicDBObject("ts", now);
          collection.save(time);
          ----------------------------
          com.mongodb.DBRef被用來表示數(shù)據(jù)庫引用(官方一般建議手動(dòng)引用):
          DBRef addressRef = new DBRef(db, "foo.bar", address_id);
          DBObject address = addressRef.fetch();
          DBObject person = BasicDBObjectBuilder.start()
              .add("name", "Fred")
              .add("address", addressRef)
              .get();
          collection.save(person);
          DBObject fred = collection.findOne();
          DBRef addressObj = (DBRef)fred.get("address");
          addressObj.fetch()
          ----------------------------
          二進(jìn)制數(shù)據(jù):
          java中的字節(jié)數(shù)組會(huì)自動(dòng)被包裝成二進(jìn)制數(shù)據(jù)存入數(shù)據(jù)庫。
          二進(jìn)制類可以被用來表示二進(jìn)制對象,這可以用來取一個(gè)自定義類型的字節(jié)。
          ----------------------------
          時(shí)間戳數(shù)據(jù)(BSONTimestamp對象):
          時(shí)間戳數(shù)據(jù)是一個(gè)mongoDB使用的特殊對象,表示一個(gè)(以秒為單位的時(shí)間,自增ID)的鍵值對,這被用于主從復(fù)制的操作日志中。
          ----------------------------
          代碼對象:
          用于表示javascript代碼,例如保存可執(zhí)行的方法到system.js集合中。
          Code和CodeWScope類用來表示這種數(shù)據(jù)。
          注意有些方法(比如map/reduce)接收字符串,但是在驅(qū)動(dòng)中將其包裝為代碼對象。
          ----------------------------
          嵌套對象:
          在javascript里面這樣一個(gè)json文檔:
          {
              "x" : {
                  "y" : 3
              }
          }
          在java中對應(yīng)的形式是:
          BasicDBObject y = new BasicDBObject("y", 3);
          BasicDBObject x = new BasicDBObject("x", y);
          ----------------------------
          數(shù)組:
          java中所有實(shí)現(xiàn)List接口的都被以數(shù)組形式在數(shù)據(jù)庫中保存:
          所以如果想保存這樣一個(gè)json:
          {
              "x" : [
                  1,
                  2,
                  {"foo" : "bar"},
                  4
              ]
          }
          在java中可以這么做:
          ArrayList x = new ArrayList();
          x.add(1);
          x.add(2);
          x.add(new BasicDBObject("foo", "bar"));
          x.add(4);
          BasicDBObject doc = new BasicDBObject("x", x);
          -------------------------------------------------------------
          在java驅(qū)動(dòng)中的優(yōu)先讀取策略(Read Preferences)和節(jié)點(diǎn)標(biāo)記(Tagging)
          http://www.mongodb.org/display/DOCS/Read+Preferences+and+Tagging+in+The+Java+Driver
          用來允許應(yīng)用程序開發(fā)者能將讀寫操作指定在某個(gè)主從集合的成員節(jié)點(diǎn)上。
          2.2版本在節(jié)點(diǎn)標(biāo)記(node tagging)帶來些新的東西讓你能更好的控制你的數(shù)據(jù)的讀寫。
          java驅(qū)動(dòng)的2.9.0集成了mongodb2.2提供的所有新特性。
          ----------------------------
          優(yōu)先讀取策略(Read Preferences):
          用于提供客戶端程序選擇那個(gè)節(jié)點(diǎn)來讀取,有以下五個(gè)選擇:
          PRIMARY : 默認(rèn)方式,從主節(jié)點(diǎn)讀取,如果主節(jié)點(diǎn)不可用則拋出異常,無法與標(biāo)簽(tags)一起使用。
          PRIMARY PREFERRED : 優(yōu)先讀取主節(jié)點(diǎn),失敗的話從副節(jié)點(diǎn)讀取。
          SECONDARY : 從副節(jié)點(diǎn)讀取,失敗則拋異常。
          SECONDARY PREFERRED : 優(yōu)先讀取副節(jié)點(diǎn),失敗則從主節(jié)點(diǎn)讀取。
          NEAREST : 從最近的節(jié)點(diǎn)讀取,“最近”的定義為ping的響應(yīng)時(shí)間最短(也得滿足15毫秒以內(nèi))。
          java實(shí)現(xiàn):類ReadPreference的工廠模式可以創(chuàng)建對應(yīng)上述五種策略的對象:
          ReadPreference.primary();
          ReadPreference.primaryPreferred();
          ReadPreference.secondary();
          ReadPreference.secondaryPreferred();
          ReadPreference.nearest();
          例如:假設(shè)我們的應(yīng)用需要保持強(qiáng)一致性(寫入的數(shù)據(jù)立即可以被讀出),但是我們又希望萬一主庫掛掉以后,從庫依然可以讀取。這種情況下,我們需要選擇PRIMARY PREFERRED模式:
          ReadPreference preference = ReadPreference.primaryPreferred();
          DBCursor cur = new DBCursor(collection, query, null, preference);
          java驅(qū)動(dòng)保持著各個(gè)節(jié)點(diǎn)的狀態(tài)信息(每隔一段時(shí)間ping一次所有節(jié)點(diǎn)),在這個(gè)例子中,java驅(qū)動(dòng)會(huì)檢測到主庫的掛掉,從而將讀操作指向從節(jié)點(diǎn)。
          ----------------------------
          節(jié)點(diǎn)標(biāo)記(Tags):
          在mongoDB2.0之后,主從集群中的每一個(gè)節(jié)點(diǎn)都可以被標(biāo)記一個(gè)描述,稱為tags??梢杂脕順?biāo)記一個(gè)節(jié)點(diǎn)的位置,和在集群中的從屬關(guān)系或者特性。這可以讓你的應(yīng)用程序從指定節(jié)點(diǎn)中讀寫。
          例子:
          假設(shè)我們要運(yùn)行一個(gè)三節(jié)點(diǎn)的主從集群,三個(gè)節(jié)點(diǎn)分別在三個(gè)不同地理位置的數(shù)據(jù)中心當(dāng)中。我們希望確保我們的數(shù)據(jù)在災(zāi)難中也可以恢復(fù),所以我們對每一個(gè)節(jié)點(diǎn)標(biāo)記其地理位置,配置文件樣例如下:
          foo:SECONDARY> rs.conf()
          {
              "_id":"foo",
              "version":103132,
               "members":[
                   {
                        "_id":0,
                         "host":"localhost:27017",
                         "priority":10,
                         "tags":{
                             "datacenter":"Los Angeles",
                              "region":"US_West"
                         }
                    },
                    {
                        "_id":1,
                         "host":"localhost:27018",
                         "tags":{
                             "datacenter":"San Jose",
                              "region":"US_West"
                         }
                    },
                    {
                        "_id":2,
                         "host":"localhost:27019",
                         "tags":{
                             "datacenter":"Richmond",
                              "region":"US_Eest"
                         }
                    }
               ],
               "settings":{
                   "getLastErrorModes":{
                        "DRSafe":{
                             "region":2
                         }
                    }
               }
          }
          foo:SECONDARY>
          注意上面settings字段,我們定義了一個(gè)新的getLastErrorModes對象,鍵為DRSafe。當(dāng)我們客戶端采用此錯(cuò)誤模式作為WriteConcern的時(shí)候,它會(huì)使寫操作在完成前復(fù)制到至少兩個(gè)節(jié)點(diǎn)上。下面是使用的例子:
          //使用自定義的getLastErrorMode創(chuàng)建WriteConcern
          WriteConcern concern = new WriteConcern("DRSafe");
          //使用自定義的WriteConcern進(jìn)行寫操作
          coll.insert(new BasicDBObject("name", "simple doc"), concern);
          ----------------------------
          在優(yōu)先讀取策略(Read Preferences)中使用節(jié)點(diǎn)標(biāo)記(Tags):
          假如我們想要將讀請求發(fā)送到最近的節(jié)點(diǎn)上以便減少請求延時(shí):
          DBObject query = new BasicDBObject("name", "simple doc")
          DBObject result = coll.findOne(query, null, ReadPreference.nearest());
          這樣java驅(qū)動(dòng)會(huì)自動(dòng)將讀請求發(fā)送到ping值最小的節(jié)點(diǎn)(也有可能是主節(jié)點(diǎn))。
          但是,如果我們的java驅(qū)動(dòng)可以確定自己的請求發(fā)送源位置,那么就可以明確指定將讀請求發(fā)送到距離最近的數(shù)據(jù)中心。再看上面的例子,假如這個(gè)讀請求來自南加利福尼亞,我們就明確指定這個(gè)讀請求到Los Angeles數(shù)據(jù)中心:
          // initialize a properly tagged read preference
          ReadPreference tagged_pref = ReadPreference.secondaryPreferred(new BasicDBObject("datacenter", "Los Angeles"));
          // include the tagged read preference in this request}}
          DBObject result = coll.findOne(}}
          new BasicDBObject("name", "simple doc"), null, tagged_pref);
          下面的例子指定多個(gè)tag,如果讀請求在Los Angeles失敗,則發(fā)送到"US_West"區(qū)域的某個(gè)節(jié)點(diǎn):
          // read from either LA or US_West
          DBObject tagSetOne = new BasicDBObject("datacenter", "Los Angeles"):
          DBObject tagSetTwo = new BasicDBObject("region", "US_West");
          ReadPreference pref = ReadPreference.primaryPreferred(tagSetOne, tagSetTwo);
          下面的例子同樣指定多個(gè)tag,首先請求"datacenter=Los Angeles"且"rack=1"的節(jié)點(diǎn),如果失敗則查找"region=US_West"的節(jié)點(diǎn)
          // read from either LA or US_West
          DBObject tagSetOne = new BasicDBObject("datacenter", "Los Angeles");
          tagSetOne.put("rack", "1");
          DBObject tagSetTwo = new BasicDBObject("region", "US_West");
          ReadPreference pref = ReadPreference.primaryPreferred(tagSetOne, tagSetTwo);
          優(yōu)先讀取策略(Read Preferences)可以在operation, collection, DB, Mongo, MongoOptions, MongoURI各個(gè)級別來設(shè)置,而且設(shè)置會(huì)以slaveOK和WriteConcer類似的方式來繼承。
          優(yōu)先讀取策略(Read Preferences)在支持主從復(fù)制的服務(wù)器上(1.6+)都可以使用。
          在優(yōu)先讀取策略(Read Preferences)中使用節(jié)點(diǎn)標(biāo)記(Tags)在所有支持節(jié)點(diǎn)標(biāo)記的服務(wù)器(2.0+)都可以使用。
          在分片(shard)上使用節(jié)點(diǎn)標(biāo)記(Tags),必須是2.2+版本的服務(wù)器才可以。

          posted on 2012-09-22 22:32 王星游 閱讀(4895) 評論(1)  編輯  收藏 所屬分類: java

          評論

          # re: mongoDB java驅(qū)動(dòng)學(xué)習(xí)筆記[未登錄]  回復(fù)  更多評論   

          mongodb 3.0 該用什么方法確保連接不被釋放

          db.requestStart();

          db.requestDone(); 3.0 中是使用說明方法
          2016-04-08 11:37 | echo
          主站蜘蛛池模板: 陆河县| 丰宁| 西和县| 墨江| 平潭县| 永吉县| 曲阜市| 济阳县| 望江县| 巢湖市| 精河县| 绥宁县| 炉霍县| 湘乡市| 延庆县| 原阳县| 柳林县| 武陟县| 长顺县| 安平县| 十堰市| 美姑县| 柳林县| 溧阳市| 洞头县| 青冈县| 龙井市| 牡丹江市| 灌云县| 广饶县| 惠安县| 兴化市| 桃园市| 和硕县| 普宁市| 邹城市| 鄂托克旗| 潞西市| 高安市| 时尚| 安陆市|