[컴][db] mongodb 에서 기존의 값을 이용해서 update 하는 방법

 

기존의 값을 이용해서 update / 다른 field 값을 이용해서 update / 업데이트 / 몽고db / query

mongodb 에서 기존의 값을 이용해서 update 하는 방법

ref.1 에서 아래와 같이 이야기 한다.

Using the aggregation pipeline allows for a more expressive update statement, such as expressing conditional updates based on current field values or updating one field using the value of another field(s).

위 문서에서도 이야기 하듯이, aggregation 을 이용해서 현재값을 기반으로 새로운 값을 update 하거나, 다른 field 의 값을 이용해서 update 할 수 있다.

주의할 점은 aggregation 이기에 [] 를 써야한다는 것이다.

2개의 update 동작도 같이 실행할 수 있다.

// mycoll
{ _id: 1, test: [1,2,3], testval: 5}

// query
// myid 에 _id 값을 넣고(field 가 없으면 생성), testval2 에는 testval 을 넣는다.
db.mycoll.update(
  { testval : {$ne: 5}},
  [
    { $set : {myid: "$_id"} },
    { $set : {testval2: "$testval"}}
  ]
)

더 많은 예제는 ref.1 에서 볼 수 있다.

See Also

  1. MongoDB Update Document using existing value - Stack Overflow

Reference

  1. Updates with Aggregation Pipeline — MongoDB Manual

[컴][db] mongodb query example

mongo aggregation example

작성중…

mongodb query example

verion 5.5 기준

update

db.collection.update(
  { site_id: "xxx" },
  [{ $set: {
    "title.de": { $cond: [ { $not: ["$title.de"] }, "", "$title.de" ] },
    "content.ru": { $cond: [ { $not: ["$content.ru"] }, "", "$content.ru" ] }
  }}],
  { multi: true }
)

기존의 값을 이용해서 값을 update 할 때:

db.getCollection('Album').find().snapshot().forEach(
      function (e) {
        for(var i=0; i<e.photos.length; i++) {
            e.photos[i].webPath = '/uploads'+e.photos[i].webPath;
        }
        db.getCollection('Album').save(e);
    }
)

// 
db.collection.updateMany(
  { myid: {$exists: false}, [{ $set : {myid: "$_id"} }]
)

특정 array field 에서 값 삭제

// item collection
{ item_list: ["item1", "item2", "item3"]},
{ item_list: ["item1", "item5", "item6"]}

// item_list 에 'item1' 이 있는 모든 doc 의 item_list 에서 'item1' 을 제거
db.item.updateMany(
    {
        item_list: "item1"
    },
    { $pull : {
        item_list: "item1"
    }}
)

aggregation lookup

rdbms 의 join 과 비슷. 다음은 session doc 에 event doc 을 join 하는 것(session id 를 키로 해서 join)

db.session.aggregate([
  {"$match": 
    {"time_a": { 
      "$gte" : ISODate("2022-07-21T00:30:00Z"),
      "$lt" : ISODate("2022-07-21T00:40:00Z")
    }},
  },
  {"$lookup":{
    "from": "event",
    "let": { "param_id": "$_id"},
    "pipeline": [
      { "$match":
        "type": 1,
        // join on 조건은 expr 로 해야만 동작한다.
        // "$si_of_event": $$param_id 는 동작하지 않는다
        { "$expr":
          { "$and": [
            { "$eq": [ "$si_of_event",  "$$param_id" ] },
          ]}
        }
      },
      { $project: {
        _id: 0, type: 1
      }}
    ],
    "as":"event_info"
  }},
  
])

특정 field 값이 같은 doc 끼리 특정 값을 비교해서 순위를 매기는 방법

$rank 는 1,2,2,4 로 표시 되고, $denseRank 는 1,2,2,3 으로 표시된다.

state field 의 값이 같은 것끼리 순위를 매긴다. quantity 값으로 정렬

db.cakeSales.aggregate( [
   {
      $setWindowFields: {
         partitionBy: "$state",
         sortBy: { quantity: -1 },
         output: {
            denseRankQuantityForState: {
               $denseRank: {}
            }
         }
      }
   }
] )

array size 가 1 보다 큰 것에 대한 $match

size 가 1인 경우:

db.inventory.find({tags:{$size:1}})

size 가 1보다 큰 경우:

db.invantory.find({
    $expr: {
        $gt: [{ $size: { $ifNull: ["$tags", []] } }, 0]
    }
})

// 아래는 틀린 query 이다.
db.invantory.find({
    tags: {
        $gt: [{$size: "$tags"}, 0]
    }
})

See Also

  1. 쿠…sal: [컴][웹][DB] MongoDB aggregation 예제 - max 일 때 index 얻어오는 방법
  2. Query for Documents With Array Size Greater Than 1 in MongoDB | Delft Stack

[컴][db] NoSQL 자료

 

nosql mongodb / db / 차이점 / 마소/ nosql database / db / mongo / cassandra /

NoSQL 자료

[컴] reactor의 flatMap vs map

reactor flatMap map / 차이 / flatmap, map 차이

reactor의 flatMap vs map

map 을 이용하면, 즉 map 의 mapper function 은 parameter 로 특정 type (여기서는 U라고 하자.)의 object 를 받게된다. 그러면, 이것에 대한 Flux 가 만들어진다.

이때 하나의 thread 로 작업(mapper)을 처리하기 때문에, order(순서)는 유지된다.

flatMap 의 mapper function 에서는 parameter 로 특정 type 의 Publisher<U> 를 받는다. 그리고 이 Publisher<U>를 return 한다. 그러면 이것에 대한 Flux<U> 가 만들어진다. 만약 map 을 이용해서 mapper function 에서 Publisher<U>를 return 했다면, Flux<Publisher<U>> 가 됐을 것이다.

ref 2

- `map` takes a `Function<T, U>` and returns a `Flux<U>`
- `flatMap` takes a `Function<T, Publisher<V>>` and returns a `Flux<V>`

위 표현은 개인적으로 혼란스럽다. 오히려 같은 parameter 를 가질때를 비교하는 것이 좀 더 명쾌하다.

위 kotlin 코드에서 보듯이, parameter 로 넘어오는 값들은 map 을 쓰나, flatMap 을 쓰나 다르지 않다. 다만 return 값이 달라진다. 위의 코드에서 보듯이, 

  • map 을 하면, return 한 값이 그대로 다음 stream 의 parameter 로 넘어간다.
    [1], [2], [3], ...
  • 그런데 flatMap 을 쓰면, return 으로 Mono 를 보내도, 다음 stream 에는 Mono 는 벗겨내고, 그 안의 내용(contents) 만 parameter 로 받는다.
    [1, 2, 3, ...]

즉 return 값의 변화가 필요하다면, 또는 변화가 생긴다면 flatMap 을 쓰면 된다. 개인적으로는 IntelliJ 에서 미리 parameter 로 받게되는 type 을 보여주는데 그것을 보고 이해하면 이해가 좀 쉽다.

Reference

  1. Project Reactor: map() vs flatMap() | Baeldung
  2. java - map vs flatMap in reactor - Stack Overflow

[컴][웹] MongoDB 최적화

몽고db최적화 / 몽고 최적화 / mongo db optimization/ opt / mongodb index / 빠르게 / slow

mongodb 최적화

db.collection.ensureIndex({"name" : 1})

는 name 을 ascending order 로 정렬해서 index 를 만든다는 이야기 이다.

db.collection.ensureIndex({"name" : 1}, {unique: true})

이런식으로 uniqueness 를 보장할 수도 있다.

db.collection.ensureIndex({"name" : 1}, {background: true})

이렇게 만들어진 index 는 관련 작업을 할 때 mongoDB 가 알아서 가져다 쓴다.

query 의 속도는 높여주지만, insertion 의 시간은 느려진다. insertion 할 때마다 index 를 자동으로 만들기 때문이다.(?)

index의 total size 를 RAM 에 맞추는 것이 좋다고 한다.

인덱스에 대한 성능을 측정 하려면 위의 문서를 참고하자.

에서 aggregation 중 index 의 효과를 볼 수 있는 method 에 대해 이야기 해준다.

  • $match
  • $sort
  • $limit
  • $skip

unsharded collection 들에서는 aggregation pipeline 이 명령을 수행하는데 indexing 된 field 만 사용한다면 index 가 pipeline 을 cover 할 수 있다고 한다.

$match, $limit, $skip 로 filtering 을 한 이후에 field 가 indexing 되어 있는 녀석들이라면 indexing 이 이용된다.(?)

index 개수 제한

하나의 collection 에서 64 개의 index 까지 가능

See Also

  1. 쿠…sal: [컴][db] mongodb 성능 분석, MongoDB Profiler and explain()
  2. 쿠…sal: [컴][db] mongo db profiling

[컴] build.gradle 에서 변수 선언

 

전역변수 / 전체에서 사용할 variable / 변수 선언

build.gradle 에서 변수 선언

아래처럼 buildscript.ext 에 선언하면 된다. 이것은 build.gradle 에서 가장먼저 buildscript 를 가장 먼저 처리하기 때문이다(evaluated)

buildscript {
  ext {
    localrepo = 'c:/myrepo/.m2/repository/'
  }
  repositories {
    maven {
      url localrepo
    }
  }
  dependencies {
    classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.0"
  }
}


plugins {
    id 'application' 
}

apply plugin: "org.jetbrains.kotlin.jvm"
...

repositories {
    maven {
        url localrepo
    }
    // mavenCentral() 
}

References

  1. How to set variable in build.gradle? - Stack Overflow