2015-01-28 3 views
-1

Мне нужно экспортировать записи клиентов из базы данных mongoDB. Экспортированные записи клиентов не должны иметь дублирующихся значений. «firstName + lastName + code» является ключом к DE-обнулению записи, и если в базе данных с одним и тем же ключом есть две записи, тогда мне нужно отдавать предпочтение исходному полю со значением, отличным от электронной почты.Запрос MongoDB с условной группой по заявлению

покупатель (id,firstName,lastName,code,source) сборник это.

Если есть запись 3 записи с таким же уникальным ключом и тремя разными источниками, тогда мне нужно выбрать только одну запись между двумя источниками (ТВ, Интернет) {или если есть n источников, мне нужна только одна запись} не с «электронной почтой» (как электронная почта будет выбрана, когда только одна запись присутствует с уникальным ключом и источником является электронная почта) запроса с использованием:

`db.customer.aggregate([ 
{ "$match" : { "active" : true , "dealerCode" : { "$in" : [ "111391"]} , "source" : { "$in" : [ "email","TV","internet"]}}}, 
    {$group:{"_id":{ 
        "firstName":"$personalInfo.firstName", 
        "lastName":"$personalInfo.lastName", 
        "code":"$vehicle.code"},    
     "source":{ 
        $addToSet:{"source":"$source"} 
       } 
     } 
    }, 
    {$redact: 
     {$cond:[{$eq:[{$ifNull:["$source","other"]},"email"]},"$$PRUNE","$$DESCEND"]} 
    }, 
    {$project: 
     {"source": 
      {$map: 
        {"input": 
         {$cond:[ 
         {$eq:[{$size:"$source"},0]},[{"source":"email"}],"$source"] 
         },"as":"inp","in":"$$inp.source"} 
      }, 
      "record":{"_id":1} 
     } 
    } ])` 

пример вывод: { "_id" : { "firstName" : "sGI6YaJ36WRfI4xuJQzI7A==", "lastName" : "99eQ7i+uTOqO8X+IPW+NOA==", "code" : "1GTHK23688F113955" }, "source" : [ "internet" ] } { "_id" : { "firstName" : "WYDROTF/9vs9O7XhdIKd5Q==", "lastName" : "BM18Uq/ltcbdx0UJOXh7Sw==", "code" : "1G4GE5GV5AF180133" }, "source" : [ "internet" ] } { "_id" : { "firstName" : "id+U2gYNHQaNQRWXpe34MA==", "lastName" : "AIs1G33QnH9RB0nupJEvjw==", "code" : "1G4GE5EV0AF177966" }, "source" : [ "internet" ] } { "_id" : { "firstName" : "qhreJVuUA5l8lnBPVhMAdw==", "lastName" : "petb0Qx3YPfebSioY0wL9w==", "code" : "1G1AL55F277253143" }, "source" : [ "TV" ] } { "_id" : { "firstName" : "qhreJVuUA5l8lnBPVhMAdw==", "lastName" : "6LB/NmhbfqTagbOnHFGoog==", "code" : "1GCVKREC0EZ168134" }, "source" : [ "TV", "internet" ] }

Это Задайте этот вопрос:

+1

Извинения для комментариев здесь изначально кто-то получил довольно подчеркнул! Я не знаю Монго, но, надеюсь, кто-то сможет ответить на этот вопрос. Я думаю, что здесь достаточно информации, чтобы ответить на этот вопрос. – halfer

ответ

2

Ваш код не работает, потому что $cond не является оператором аккумулятора. Только операторы аккумуляторов these могут использоваться на этапе $group.

Предполагая, что ваши записи содержат не более двух возможных значений source, как вы упоминаете в своем вопросе, вы можете добавить условную $project этапа и изменить стадию $group как,

Код:

db.customer.aggregate([ 
{$group:{"_id":{"id":"$id", 
       "firstName":"$firstName", 
       "lastName":"$lastName", 
       "code":"$code"}, 
     "sourceA":{$first:"$source"}, 
     "sourceB":{$last:"$source"}}}, 
{$project:{"source":{$cond:[{$eq:["$sourceA","email"]}, 
          "$sourceB", 
          "$sourceA"]}}} 
]) 

В случае, если для источника может быть больше двух возможных значений, вы можете сделать следующее:

  • Group by id, firstName, lastName и code. Накопите уникальные значения source, используя оператор $addToSet.
  • Использовать $redact для хранения только значений, отличных от email.
  • Project обязательные поля, если массив source пуст (все элементы были удалены), добавьте значение email.
  • Unwind Исходное поле, чтобы отобразить его как поле, а не массив. (опционально)

Код:

db.customer.aggregate([ 
{$group:{"_id":{"id":"$id", 
       "firstName":"$firstName", 
       "lastName":"$lastName", 
       "code":"$code"}, 
     "sourceArr":{$addToSet:{"source":"$source"}}}}, 
{$redact:{$cond:[{$eq:[{$ifNull:["$source","other"]},"email"]}, 
      "$$PRUNE", 
      "$$DESCEND"]}}, 
{$project:{"source":{$map:{"input": 
          {$cond:[{$eq:[{$size:"$sourceArr"}, 
             0]}, 
            [{"source":"item"}], 
            "$sourceArr"]}, 
          "as":"inp", 
          "in":"$$inp.source"}}}} 
]) 
+0

Не могли бы вы кратко объяснить свойство redact и {$ redact: {$ cond: [{$ eq: [{$ ifNull: ["$ source", "other"]}, "email"]}, " $$ PRUNE ", " $$ DESCEND "]}}, –

+0

@RishabhPandey - оператор' redact' принимает документ на определенном уровне, проверяет, соответствует ли документ на этом уровне определенному условию на основе вывода условие, оно может либо опускаться в поддоны документа, либо обрезать документ, либо сохранить документ как есть, а не спускаться. Если он захочет спуститься во вспомогательные документы, то такое же условие будет применено к этому документу и рекурсивно обходит вспомогательные документы, если не может быть применено сохранение или чернослив, или не существует дополнительных поддокументов. Действие действует только на документы и вспомогательные документы. – BatScream

+0

@RishabhPandey Вы очень желанны. Да, все будет хорошо. Это зависит от вашего варианта использования. Если возможно, вы можете хранить источник как массив значений. Это будет лучше с точки зрения дизайна. Да, вы можете сделать это с помощью '$ project', чтобы получить другие поля. Вы можете добавить новый вопрос, если вы провалились после нескольких попыток. Это определенно возможно. – BatScream

Смежные вопросы