MongoDB
 sql >> база данни >  >> NoSQL >> MongoDB

Изчислени полета за групиране в MongoDB

Всъщност можете първо да направите нещо подобно с „project“, но за мен е малко неинтуитивно да се изисква $project етап преди ръка:

    Aggregation agg = newAggregation(
        project("quantity")
            .andExpression("dayOfMonth(date)").as("day")
            .andExpression("month(date)").as("month")
            .andExpression("year(date)").as("year")
            .andExpression("price * quantity").as("totalAmount"),
        group(fields().and("day").and("month").and("year"))
            .avg("quantity").as("averavgeQuantity")
            .sum("totalAmount").as("totalAmount")
            .count().as("count")
    );

Както казах, контраинтуитивно, тъй като трябва просто да можете да декларирате всичко това под $group етап, но помощниците изглежда не работят по този начин. Сериализацията изглежда малко смешна (обвива аргументите на оператора за дата с масиви), но изглежда работи. Но все пак това са два етапа на тръбопровод, а не един.

Какъв е проблемът с това? Е, като разделя етапите на етапите, частта „проект“ принуждава обработката на всички документи в конвейера, за да получи изчислените полета, което означава, че преминава през всичко, преди да премине към груповия етап.

Разликата във времето за обработка може ясно да се види, като стартирате заявките и в двете форми. С отделен етап на проекта изпълнението на моя хардуер отнема три пъти повече време от заявката, при която всички полета се изчисляват по време на операцията „група“.

Така че изглежда единственият настоящ начин да се конструира това правилно е като се изгради сам тръбопроводният обект:

    ApplicationContext ctx =
            new AnnotationConfigApplicationContext(SpringMongoConfig.class);
    MongoOperations mongoOperation = (MongoOperations) ctx.getBean("mongoTemplate");

    BasicDBList pipeline = new BasicDBList();
    String[] multiplier = { "$price", "$quantity" };

    pipeline.add(
        new BasicDBObject("$group",
            new BasicDBObject("_id",
                new BasicDBObject("month", new BasicDBObject("$month", "$date"))
                    .append("day", new BasicDBObject("$dayOfMonth", "$date"))
                    .append("year", new BasicDBObject("$year", "$date"))
            )
            .append("totalPrice", new BasicDBObject(
                "$sum", new BasicDBObject(
                    "$multiply", multiplier
                )
            ))
            .append("averageQuantity", new BasicDBObject("$avg", "$quantity"))
            .append("count",new BasicDBObject("$sum",1))
        )
    );

    BasicDBObject aggregation = new BasicDBObject("aggregate","collection")
        .append("pipeline",pipeline);

    System.out.println(aggregation);

    CommandResult commandResult = mongoOperation.executeCommand(aggregation);

Или ако всичко това ви изглежда кратко, винаги можете да работите с източника на JSON и да го анализирате. Но, разбира се, трябва да е валиден JSON:

    String json = "[" +
        "{ \"$group\": { "+
            "\"_id\": { " +
                "\"month\": { \"$month\": \"$date\" }, " +
                "\"day\": { \"$dayOfMonth\":\"$date\" }, " +
                "\"year\": { \"$year\": \"$date\" } " +
            "}, " +
            "\"totalPrice\": { \"$sum\": { \"$multiply\": [ \"$price\", \"$quantity\" ] } }, " +
            "\"averageQuantity\": { \"$avg\": \"$quantity\" }, " +
            "\"count\": { \"$sum\": 1 } " +
        "}}" +
    "]";

    BasicDBList pipeline = (BasicDBList)com.mongodb.util.JSON.parse(json);


  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Не мога да получа allowDiskUse:True за работа с pymongo

  2. Условна проекция в mongodb с помощта на c# драйвер

  3. Mongodb .net async чака

  4. shell скрипт - проверете дали сървърът на mongod работи

  5. RoR:Mongoid и форма създават хеш