这里有一个应用程序,实现了我认为你需要的逻辑。它使用异步Java驱动程序的辅助类来帮助构建正确的管道。在代码的最后,我们插入了99个文档。33个字段值为空,33个有值,33个没有值。该应用程序总共获得了66个结果,我认为这就是你想要的结果。
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;
public class SumIfExists {
private final static Random random = new Random(123456789L);
private final static MongoClient client = MongoFactory
.createClient("mongodb://localhost:27017/");
private final static MongoCollection theCollection = client.getDatabase(
"db").getCollection("collection");
public static void main(String[] args) throws IOException {
Aggregate.Builder builder = Aggregate.builder();
String fieldName = "myfieldname";
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()));
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());
}
doc.add("a", random.nextBoolean());
doc.add("b", random.nextInt());
doc.add("c", random.nextLong());
doc.add("etc", random.nextLong());
theCollection.insert(doc);
}
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
}]
我离正确答案很近吗?
罗布。
$ne
,但我仍然遇到了一些问题,特别是与null
相关的问题。 - Jeff Storey$ifNull
在这里起作用。如果不为空,则返回1,如果为空或不存在,则返回0。 - Jeff Storey$ifNull
:我认为你可以在$cond
中用$eq
包装它,以获得正确的逻辑。类似这样:'$cond' : [ { '$eq' : [ { '$ifNull' : [ '$myfieldname', ObjectId('52cb90166c4a281586e13465') ] }, ObjectId('52cb90166c4a281586e13465') ] }, 0, 1 ] - Rob Moore$myfieldname
有个打字错误。让我花几分钟了解一下你对$ifNull
的方法,并看看它是如何工作的。稍后我会回复你。感谢你的帮助。 - Jeff Storey