【问题标题】:MongoDB 3 Java check if collection existsMongoDB 3 Java检查集合是否存在
【发布时间】:2015-11-01 18:12:48
【问题描述】:

我有以下问题:

我正在使用 MongoDB 3 的 Java 驱动程序。

在版本 2 中,可以执行 DB.collectionExists(name) 来检查所选数据库中是否存在集合。

在从 DB 切换到 MongoDatabase 的版本 3 中,此方法不再存在。

如何确定数据库中是否存在集合?我尝试使用 listCollectionNames() 遍历集合,但这似乎非常无效。

感谢您的帮助

【问题讨论】:

    标签: java mongodb


    【解决方案1】:

    你是对的。似乎 3.0.x 版本的 MongoDB 驱动程序没有通过直接的“集合存在吗?”方法移植到MongoDatabase

    正如您已经提到的,您的一种选择是遍历listCollectionNames() 的结果。虽然这似乎无效,但它非常类似于DB.collectionExists(String) 方法的实现。下面的代码sn-p是从mongo-java-driver source中的DB.java类复制过来的:

    public boolean collectionExists(final String collectionName) {
        Set<String> collectionNames = getCollectionNames();
        for (final String name : collectionNames) {
            if (name.equalsIgnoreCase(collectionName)) {
                return true;
            }
        }
        return false;
    }
    

    您还可以通过调用getDB 方法从MongoClient 获取DB 而不是MongoDatabase。这使您可以访问 已弃用collectionExists 方法。当然,我不推荐第二种方法,因为如前所述,已弃用

    因此,通过listCollectionNames 方法进行迭代。

    【讨论】:

    • 感谢您的回复没有查看驱动程序代码。如果没有其他方法,我会给自己写一个简短的函数
    • 根据getDB 的Javadoc,DBDBCollectionDBCursor 类将在未来被弃用,因此使用替换是明智的(例如MongoDatabase)现在。见github.com/mongodb/mongo-java-driver/blob/master/driver/src/…
    • @Paul 是的!您的声明与我在帖子中提到的所有内容(粗体、斜体和链接)相呼应。我同意 100%。 :)
    • @whyceewhite 为什么你使用“equalsIgnoreCase”而不是“equals”?集合名称区分大小写
    • @zeugor 您所指的代码(包含equalsIngoreCase)直接来自MongoDB 的驱动程序源代码。我不确定他们为什么会忽略这种情况,因为正如您所指出的,集合名称区分大小写。但请注意,Mongodb 已弃用此方法。
    【解决方案2】:
    MongoIterable <String> collection =  database.listCollectionNames();
        for(String s : collection) {
            if(s.equals("collectionName")) {
                return true;
    
            }
        }
        return false;
    }
    

    【讨论】:

      【解决方案3】:

      对于仍在寻找的人: 假设您有名为“db”的 MongoDatabase 实例

      try {
              db.createCollection("myCol");
          } catch (MongoCommandException e) {
              System.err.println("Collection Exists");
          }
      

      【讨论】:

        【解决方案4】:

        另一种方法是使用MongoIterable.into 函数将这些添加到可以调用contains("collectionName") 的目标ArrayList。

        boolean collectionExists = client.getDatabase("dbName").listCollectionNames()
            .into(new ArrayList<String>()).contains("collectionName")
        

        【讨论】:

          【解决方案5】:

          我在搜索完全相同的问题时发现了这篇文章。使用最新的驱动,即:

          <!-- Mongo driver, GeoJson with Jackson, Gson for Mongo (Jongo) -->
          <dependency>
              <groupId>org.mongodb</groupId>
              <artifactId>mongo-java-driver</artifactId>
              <version>3.3.0</version>
          </dependency>
          

          有人可能想使用:

          public boolean collectionExists(final String db, final String collectionName) {
              final MongoDatabase database = client.getDatabase(db);
              if (database == null) {
                      return false;
              }
          
              final MongoIterable<String> iterable = database.listCollectionNames();
              try (final MongoCursor<String> it = iterable.iterator()) {
                  while (it.hasNext()) {
                      if (it.next().equalsIgnoreCase(collectionName)) {
                          return true;
                      }
                  }
              }
          
              return false;
          }
          

          【讨论】:

          • 嗨 Kiuz,您的 mongoDB 似乎有问题,也许您有一个具有该名称的数据库并将其删除,但它仍然在元信息中?如果我尝试做你描述的事情,我会得到正确的结果。你的客户端连接了吗?我们在生产中使用这个代码 sn-p 并且它工作得很好。我做了一些进一步的测试,如果我能以某种方式重现你的描述,请告诉你。
          • 别担心,希望代码对您有所帮助!顺便提一句。对评论投反对票的人会很好地解决问题。
          【解决方案6】:

          当我试图找到一种检查集合是否存在的有效方法时,我偶然发现了这篇文章。由于我的数据库中有超过 50k 个集合,因此使用 listCollectionNames() 方法效率极低。

          我所做的是使用db.collection.count() 方法,如果它返回一个非零值,那么我会将其视为不存在的集合。当然,这不是百分百正确的,因为可能有一个包含零条目的集合,而这种方法会将其视为不存在的集合。但是对于 MongoDB 中的大多数场景,一个集合只有在它至少有一个文档时才有意义。以下是示例代码,

          public boolean isCollectionExists(DB db, String collectionName) 
          {
          
              DBCollection table = db.getCollection(collectionName);
              return (table.count()>0)?true:false;
          }
          

          【讨论】:

          • 好主意,但正如您已经说过的,它不能保证有效。顺便说一句,您可以改写return table.count() &gt; 0;,因为这是一个有效的布尔表达式。
          • @Frozn 感谢您的提示!我还想澄清一下,只要您没有设计为空的集合,它就可以保证工作。
          • 这实际上不起作用,另一种解决方法是创建一个集合,如果它已经存在则抛出异常,因此您可以检查错误,如果它包含“NamespaceExists”,那么你知道收藏就在那里。否则使用上面的列表和包含检查,如果你不想要这种温和的 hacky 方式。
          猜你喜欢
          • 2018-02-27
          • 2018-08-11
          • 1970-01-01
          • 2022-01-04
          • 2012-11-06
          • 1970-01-01
          • 2020-08-31
          • 1970-01-01
          相关资源
          最近更新 更多