mongo java条件求和,如果不为null

 完美美容店 发布于 2023-02-06 10:14

我正在使用mongo java驱动程序并尝试计算特定字段不为null或不存在的所有文档.这是我到目前为止所拥有的:

String field = "myfieldname";
BasicDBObject notNull = new BasicDBObject(field,BasicDBObject("$ne",null));
List condition = Arrays.asList(notNull,1,0);
BasicDBObject aggregation = new BasicDBObject("$cond",condition);
// boiler plate code to lookup my database/collection and pass the aggregation to it


这似乎不起作用.

编辑:感谢Rob Moore的帮助.以下是我最终要做的工作

BasicDBObject ifNull = new BasicDBObject('$ifNull',Arrays.asList('$'+field,null));
BasicDBObject neq = new BasicDBObject('$ne', Arrays.asList(null,ifNull));
return new BasicDBObject('$cond', Arrays.asList(neq,1,0);

Rob Moore.. 5

这是一个实现我认为你所追求的逻辑的应用程序.它使用异步Java驱动程序的帮助程序类来帮助构建正确的管道.在代码的最后,我们插入了99个文档.33具有空字段值,33具有值,33没有值.该应用程序共有66个,我认为这是你追求的结果.

/*
 *           Copyright 2013 - Allanbank Consulting, Inc.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package stackoverflow;

import static com.allanbank.mongodb.builder.AggregationGroupField.set;
import static com.allanbank.mongodb.builder.AggregationGroupId.constantId;
import static com.allanbank.mongodb.builder.AggregationProjectFields.include;
import static com.allanbank.mongodb.builder.Find.ALL;
import static com.allanbank.mongodb.builder.expression.Expressions.cond;
import static com.allanbank.mongodb.builder.expression.Expressions.constant;
import static com.allanbank.mongodb.builder.expression.Expressions.eq;
import static com.allanbank.mongodb.builder.expression.Expressions.field;
import static com.allanbank.mongodb.builder.expression.Expressions.ifNull;
import static com.allanbank.mongodb.builder.expression.Expressions.set;

import java.io.IOException;
import java.util.Random;

import com.allanbank.mongodb.MongoClient;
import com.allanbank.mongodb.MongoCollection;
import com.allanbank.mongodb.MongoFactory;
import com.allanbank.mongodb.bson.builder.BuilderFactory;
import com.allanbank.mongodb.bson.builder.DocumentBuilder;
import com.allanbank.mongodb.bson.element.ArrayElement;
import com.allanbank.mongodb.bson.element.ObjectId;
import com.allanbank.mongodb.builder.Aggregate;

/**
 * Count the number of documents that have a particular field.
 * 
 * @see StackOverflow
 *      Question
 * 
 * @copyright 2013, Allanbank Consulting, Inc., All Rights Reserved
 */
public class SumIfExists {
    /**
     * A source of no so random values. Use a fixed seed to always get the same
     * values for fields.
     */
    private final static Random random = new Random(123456789L);

    /**
     * The handle to the MongoDB client. We assume MongoDB is running on your
     * machine on the default port of 27017.
     */
    private final static MongoClient client = MongoFactory
            .createClient("mongodb://localhost:27017/");

    /** The collection we will be using. */
    private final static MongoCollection theCollection = client.getDatabase(
            "db").getCollection("collection");

    /**
     * Run the demo.
     * 
     * @param args
     *            Command line arguments. Ignored.
     * @throws IOException
     *             On a failure closing the MongoCLient.
     */
    public static void main(String[] args) throws IOException {
        // Build the aggregation document/command.
        Aggregate.Builder builder = Aggregate.builder();

        // From the StackOverflow Question.
        String fieldName = "myfieldname";

        // A token ObjectId to use in comparisons for the null field.
        ObjectId nullToken = new ObjectId();

        builder.project(
                include("a", "b", "c", "etc"),
                set("myfieldnameExists",
                        cond(eq(ifNull(field(fieldName), constant(nullToken)),
                                constant(nullToken)), constant(0), constant(1))));
        builder.group(constantId("a"), set("count").sum("myfieldnameExists"));

        System.out.println(new ArrayElement("$pipeline", builder.build()
                .getPipeline()));

        // Insert some documents to test with.
        theCollection.delete(ALL);
        for (int i = 0; i < 99; ++i) {
            DocumentBuilder doc = BuilderFactory.start();
            if (i % 3 == 0) {
                doc.addNull(fieldName);
            }
            else if (i % 3 == 1) {
                doc.add(fieldName, random.nextDouble());
            }
            // else if (i % 3 == 2) -- Field does not exist.

            doc.add("a", random.nextBoolean());
            doc.add("b", random.nextInt());
            doc.add("c", random.nextLong());
            doc.add("etc", random.nextLong());

            theCollection.insert(doc);
        }

        // Run the aggregation.
        System.out.println(theCollection.aggregate(builder));
    }
}

代码的输出是:

'$pipeline' : [
  {
    '$project' : {
      a : 1,
      b : 1,
      c : 1,
      etc : 1,
      myfieldnameExists : {
        '$cond' : [
          {
            '$eq' : [
              {
                '$ifNull' : [
                  '$myfieldname', 
                  ObjectId('52cb94836c4a28185433c4d3')
                ]
              }, 
              ObjectId('52cb94836c4a28185433c4d3')
            ]
          }, 
          0, 
          1
        ]
      }
    }
  }, 
  {
    '$group' : {
      '_id' : 'a',
      count : { '$sum' : '$myfieldnameExists' }
    }
  }
]
[{
  '_id' : 'a',
  count : 66
}]

我接近了吗?抢.

1 个回答
  • 这是一个实现我认为你所追求的逻辑的应用程序.它使用异步Java驱动程序的帮助程序类来帮助构建正确的管道.在代码的最后,我们插入了99个文档.33具有空字段值,33具有值,33没有值.该应用程序共有66个,我认为这是你追求的结果.

    /*
     *           Copyright 2013 - Allanbank Consulting, Inc.
     * 
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     * 
     *     http://www.apache.org/licenses/LICENSE-2.0
     * 
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    package stackoverflow;
    
    import static com.allanbank.mongodb.builder.AggregationGroupField.set;
    import static com.allanbank.mongodb.builder.AggregationGroupId.constantId;
    import static com.allanbank.mongodb.builder.AggregationProjectFields.include;
    import static com.allanbank.mongodb.builder.Find.ALL;
    import static com.allanbank.mongodb.builder.expression.Expressions.cond;
    import static com.allanbank.mongodb.builder.expression.Expressions.constant;
    import static com.allanbank.mongodb.builder.expression.Expressions.eq;
    import static com.allanbank.mongodb.builder.expression.Expressions.field;
    import static com.allanbank.mongodb.builder.expression.Expressions.ifNull;
    import static com.allanbank.mongodb.builder.expression.Expressions.set;
    
    import java.io.IOException;
    import java.util.Random;
    
    import com.allanbank.mongodb.MongoClient;
    import com.allanbank.mongodb.MongoCollection;
    import com.allanbank.mongodb.MongoFactory;
    import com.allanbank.mongodb.bson.builder.BuilderFactory;
    import com.allanbank.mongodb.bson.builder.DocumentBuilder;
    import com.allanbank.mongodb.bson.element.ArrayElement;
    import com.allanbank.mongodb.bson.element.ObjectId;
    import com.allanbank.mongodb.builder.Aggregate;
    
    /**
     * Count the number of documents that have a particular field.
     * 
     * @see <a
     *      href="http://stackoverflow.com/questions/20964169/mongo-java-conditional-sum-if-exists">StackOverflow
     *      Question</a>
     * 
     * @copyright 2013, Allanbank Consulting, Inc., All Rights Reserved
     */
    public class SumIfExists {
        /**
         * A source of no so random values. Use a fixed seed to always get the same
         * values for fields.
         */
        private final static Random random = new Random(123456789L);
    
        /**
         * The handle to the MongoDB client. We assume MongoDB is running on your
         * machine on the default port of 27017.
         */
        private final static MongoClient client = MongoFactory
                .createClient("mongodb://localhost:27017/");
    
        /** The collection we will be using. */
        private final static MongoCollection theCollection = client.getDatabase(
                "db").getCollection("collection");
    
        /**
         * Run the demo.
         * 
         * @param args
         *            Command line arguments. Ignored.
         * @throws IOException
         *             On a failure closing the MongoCLient.
         */
        public static void main(String[] args) throws IOException {
            // Build the aggregation document/command.
            Aggregate.Builder builder = Aggregate.builder();
    
            // From the StackOverflow Question.
            String fieldName = "myfieldname";
    
            // A token ObjectId to use in comparisons for the null field.
            ObjectId nullToken = new ObjectId();
    
            builder.project(
                    include("a", "b", "c", "etc"),
                    set("myfieldnameExists",
                            cond(eq(ifNull(field(fieldName), constant(nullToken)),
                                    constant(nullToken)), constant(0), constant(1))));
            builder.group(constantId("a"), set("count").sum("myfieldnameExists"));
    
            System.out.println(new ArrayElement("$pipeline", builder.build()
                    .getPipeline()));
    
            // Insert some documents to test with.
            theCollection.delete(ALL);
            for (int i = 0; i < 99; ++i) {
                DocumentBuilder doc = BuilderFactory.start();
                if (i % 3 == 0) {
                    doc.addNull(fieldName);
                }
                else if (i % 3 == 1) {
                    doc.add(fieldName, random.nextDouble());
                }
                // else if (i % 3 == 2) -- Field does not exist.
    
                doc.add("a", random.nextBoolean());
                doc.add("b", random.nextInt());
                doc.add("c", random.nextLong());
                doc.add("etc", random.nextLong());
    
                theCollection.insert(doc);
            }
    
            // Run the aggregation.
            System.out.println(theCollection.aggregate(builder));
        }
    }
    

    代码的输出是:

    '$pipeline' : [
      {
        '$project' : {
          a : 1,
          b : 1,
          c : 1,
          etc : 1,
          myfieldnameExists : {
            '$cond' : [
              {
                '$eq' : [
                  {
                    '$ifNull' : [
                      '$myfieldname', 
                      ObjectId('52cb94836c4a28185433c4d3')
                    ]
                  }, 
                  ObjectId('52cb94836c4a28185433c4d3')
                ]
              }, 
              0, 
              1
            ]
          }
        }
      }, 
      {
        '$group' : {
          '_id' : 'a',
          count : { '$sum' : '$myfieldnameExists' }
        }
      }
    ]
    [{
      '_id' : 'a',
      count : 66
    }]
    

    我接近了吗?抢.

    2023-02-06 10:16 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有